]> git.sesse.net Git - ffmpeg/blob - ffserver.c
5076339497eeeeca5da450e27cc14db6c59ec373
[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 <sys/time.h>
59 #include <time.h>
60 #include <sys/wait.h>
61 #include <signal.h>
62 #if HAVE_DLFCN_H
63 #include <dlfcn.h>
64 #endif
65
66 #include "cmdutils.h"
67
68 const char program_name[] = "ffserver";
69 const int program_birth_year = 2000;
70
71 static const OptionDef options[];
72
73 enum HTTPState {
74     HTTPSTATE_WAIT_REQUEST,
75     HTTPSTATE_SEND_HEADER,
76     HTTPSTATE_SEND_DATA_HEADER,
77     HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
78     HTTPSTATE_SEND_DATA_TRAILER,
79     HTTPSTATE_RECEIVE_DATA,
80     HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
81     HTTPSTATE_READY,
82
83     RTSPSTATE_WAIT_REQUEST,
84     RTSPSTATE_SEND_REPLY,
85     RTSPSTATE_SEND_PACKET,
86 };
87
88 static const char *http_state[] = {
89     "HTTP_WAIT_REQUEST",
90     "HTTP_SEND_HEADER",
91
92     "SEND_DATA_HEADER",
93     "SEND_DATA",
94     "SEND_DATA_TRAILER",
95     "RECEIVE_DATA",
96     "WAIT_FEED",
97     "READY",
98
99     "RTSP_WAIT_REQUEST",
100     "RTSP_SEND_REPLY",
101     "RTSP_SEND_PACKET",
102 };
103
104 #define MAX_STREAMS 20
105
106 #define IOBUFFER_INIT_SIZE 8192
107
108 /* timeouts are in ms */
109 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
110 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
111
112 #define SYNC_TIMEOUT (10 * 1000)
113
114 typedef struct RTSPActionServerSetup {
115     uint32_t ipaddr;
116     char transport_option[512];
117 } RTSPActionServerSetup;
118
119 typedef struct {
120     int64_t count1, count2;
121     int64_t time1, time2;
122 } DataRateData;
123
124 /* context associated with one connection */
125 typedef struct HTTPContext {
126     enum HTTPState state;
127     int fd; /* socket file descriptor */
128     struct sockaddr_in from_addr; /* origin */
129     struct pollfd *poll_entry; /* used when polling */
130     int64_t timeout;
131     uint8_t *buffer_ptr, *buffer_end;
132     int http_error;
133     int post;
134     int chunked_encoding;
135     int chunk_size;               /* 0 if it needs to be read */
136     struct HTTPContext *next;
137     int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
138     int64_t data_count;
139     /* feed input */
140     int feed_fd;
141     /* input format handling */
142     AVFormatContext *fmt_in;
143     int64_t start_time;            /* In milliseconds - this wraps fairly often */
144     int64_t first_pts;            /* initial pts value */
145     int64_t cur_pts;             /* current pts value from the stream in us */
146     int64_t cur_frame_duration;  /* duration of the current frame in us */
147     int cur_frame_bytes;       /* output frame size, needed to compute
148                                   the time at which we send each
149                                   packet */
150     int pts_stream_index;        /* stream we choose as clock reference */
151     int64_t cur_clock;           /* current clock reference value in us */
152     /* output format handling */
153     struct FFStream *stream;
154     /* -1 is invalid stream */
155     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
156     int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
157     int switch_pending;
158     AVFormatContext fmt_ctx; /* instance of FFStream for one user */
159     int last_packet_sent; /* true if last data packet was sent */
160     int suppress_log;
161     DataRateData datarate;
162     int wmp_client_id;
163     char protocol[16];
164     char method[16];
165     char url[128];
166     int buffer_size;
167     uint8_t *buffer;
168     int is_packetized; /* if true, the stream is packetized */
169     int packet_stream_index; /* current stream for output in state machine */
170
171     /* RTSP state specific */
172     uint8_t *pb_buffer; /* XXX: use that in all the code */
173     AVIOContext *pb;
174     int seq; /* RTSP sequence number */
175
176     /* RTP state specific */
177     enum RTSPLowerTransport rtp_protocol;
178     char session_id[32]; /* session id */
179     AVFormatContext *rtp_ctx[MAX_STREAMS];
180
181     /* RTP/UDP specific */
182     URLContext *rtp_handles[MAX_STREAMS];
183
184     /* RTP/TCP specific */
185     struct HTTPContext *rtsp_c;
186     uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
187 } HTTPContext;
188
189 /* each generated stream is described here */
190 enum StreamType {
191     STREAM_TYPE_LIVE,
192     STREAM_TYPE_STATUS,
193     STREAM_TYPE_REDIRECT,
194 };
195
196 enum IPAddressAction {
197     IP_ALLOW = 1,
198     IP_DENY,
199 };
200
201 typedef struct IPAddressACL {
202     struct IPAddressACL *next;
203     enum IPAddressAction action;
204     /* These are in host order */
205     struct in_addr first;
206     struct in_addr last;
207 } IPAddressACL;
208
209 /* description of each stream of the ffserver.conf file */
210 typedef struct FFStream {
211     enum StreamType stream_type;
212     char filename[1024];     /* stream filename */
213     struct FFStream *feed;   /* feed we are using (can be null if
214                                 coming from file) */
215     AVDictionary *in_opts;   /* input parameters */
216     AVInputFormat *ifmt;       /* if non NULL, force input format */
217     AVOutputFormat *fmt;
218     IPAddressACL *acl;
219     char dynamic_acl[1024];
220     int nb_streams;
221     int prebuffer;      /* Number of millseconds early to start */
222     int64_t max_time;      /* Number of milliseconds to run */
223     int send_on_key;
224     AVStream *streams[MAX_STREAMS];
225     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
226     char feed_filename[1024]; /* file name of the feed storage, or
227                                  input file name for a stream */
228     char author[512];
229     char title[512];
230     char copyright[512];
231     char comment[512];
232     pid_t pid;  /* Of ffmpeg process */
233     time_t pid_start;  /* Of ffmpeg process */
234     char **child_argv;
235     struct FFStream *next;
236     unsigned bandwidth; /* bandwidth, in kbits/s */
237     /* RTSP options */
238     char *rtsp_option;
239     /* multicast specific */
240     int is_multicast;
241     struct in_addr multicast_ip;
242     int multicast_port; /* first port used for multicast */
243     int multicast_ttl;
244     int loop; /* if true, send the stream in loops (only meaningful if file) */
245
246     /* feed specific */
247     int feed_opened;     /* true if someone is writing to the feed */
248     int is_feed;         /* true if it is a feed */
249     int readonly;        /* True if writing is prohibited to the file */
250     int truncate;        /* True if feeder connection truncate the feed file */
251     int conns_served;
252     int64_t bytes_served;
253     int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
254     int64_t feed_write_index;   /* current write position in feed (it wraps around) */
255     int64_t feed_size;          /* current size of feed */
256     struct FFStream *next_feed;
257 } FFStream;
258
259 typedef struct FeedData {
260     long long data_count;
261     float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
262 } FeedData;
263
264 static struct sockaddr_in my_http_addr;
265 static struct sockaddr_in my_rtsp_addr;
266
267 static char logfilename[1024];
268 static HTTPContext *first_http_ctx;
269 static FFStream *first_feed;   /* contains only feeds */
270 static FFStream *first_stream; /* contains all streams, including feeds */
271
272 static void new_connection(int server_fd, int is_rtsp);
273 static void close_connection(HTTPContext *c);
274
275 /* HTTP handling */
276 static int handle_connection(HTTPContext *c);
277 static int http_parse_request(HTTPContext *c);
278 static int http_send_data(HTTPContext *c);
279 static void compute_status(HTTPContext *c);
280 static int open_input_stream(HTTPContext *c, const char *info);
281 static int http_start_receive_data(HTTPContext *c);
282 static int http_receive_data(HTTPContext *c);
283
284 /* RTSP handling */
285 static int rtsp_parse_request(HTTPContext *c);
286 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
287 static void rtsp_cmd_options(HTTPContext *c, const char *url);
288 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
289 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
290 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
291 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
292
293 /* SDP handling */
294 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
295                                    struct in_addr my_ip);
296
297 /* RTP handling */
298 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
299                                        FFStream *stream, const char *session_id,
300                                        enum RTSPLowerTransport rtp_protocol);
301 static int rtp_new_av_stream(HTTPContext *c,
302                              int stream_index, struct sockaddr_in *dest_addr,
303                              HTTPContext *rtsp_c);
304
305 static const char *my_program_name;
306 static const char *my_program_dir;
307
308 static const char *config_filename = "/etc/ffserver.conf";
309
310 static int ffserver_debug;
311 static int ffserver_daemon;
312 static int no_launch;
313 static int need_to_start_children;
314
315 /* maximum number of simultaneous HTTP connections */
316 static unsigned int nb_max_http_connections = 2000;
317 static unsigned int nb_max_connections = 5;
318 static unsigned int nb_connections;
319
320 static uint64_t max_bandwidth = 1000;
321 static uint64_t current_bandwidth;
322
323 static int64_t cur_time;           // Making this global saves on passing it around everywhere
324
325 static AVLFG random_state;
326
327 static FILE *logfile = NULL;
328
329 /* FIXME: make ffserver work with IPv6 */
330 void av_noreturn exit_program(int ret)
331 {
332     exit(ret);
333 }
334
335 /* resolve host with also IP address parsing */
336 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
337 {
338
339     if (!ff_inet_aton(hostname, sin_addr)) {
340 #if HAVE_GETADDRINFO
341         struct addrinfo *ai, *cur;
342         struct addrinfo hints;
343         memset(&hints, 0, sizeof(hints));
344         hints.ai_family = AF_INET;
345         if (getaddrinfo(hostname, NULL, &hints, &ai))
346             return -1;
347         /* getaddrinfo returns a linked list of addrinfo structs.
348          * Even if we set ai_family = AF_INET above, make sure
349          * that the returned one actually is of the correct type. */
350         for (cur = ai; cur; cur = cur->ai_next) {
351             if (cur->ai_family == AF_INET) {
352                 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
353                 freeaddrinfo(ai);
354                 return 0;
355             }
356         }
357         freeaddrinfo(ai);
358         return -1;
359 #else
360         struct hostent *hp;
361         hp = gethostbyname(hostname);
362         if (!hp)
363             return -1;
364         memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
365 #endif
366     }
367     return 0;
368 }
369
370 static char *ctime1(char *buf2)
371 {
372     time_t ti;
373     char *p;
374
375     ti = time(NULL);
376     p = ctime(&ti);
377     strcpy(buf2, p);
378     p = buf2 + strlen(p) - 1;
379     if (*p == '\n')
380         *p = '\0';
381     return buf2;
382 }
383
384 static void http_vlog(const char *fmt, va_list vargs)
385 {
386     static int print_prefix = 1;
387     if (logfile) {
388         if (print_prefix) {
389             char buf[32];
390             ctime1(buf);
391             fprintf(logfile, "%s ", buf);
392         }
393         print_prefix = strstr(fmt, "\n") != NULL;
394         vfprintf(logfile, fmt, vargs);
395         fflush(logfile);
396     }
397 }
398
399 #ifdef __GNUC__
400 __attribute__ ((format (printf, 1, 2)))
401 #endif
402 static void http_log(const char *fmt, ...)
403 {
404     va_list vargs;
405     va_start(vargs, fmt);
406     http_vlog(fmt, vargs);
407     va_end(vargs);
408 }
409
410 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
411 {
412     static int print_prefix = 1;
413     AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
414     if (level > av_log_get_level())
415         return;
416     if (print_prefix && avc)
417         http_log("[%s @ %p]", avc->item_name(ptr), ptr);
418     print_prefix = strstr(fmt, "\n") != NULL;
419     http_vlog(fmt, vargs);
420 }
421
422 static void log_connection(HTTPContext *c)
423 {
424     if (c->suppress_log)
425         return;
426
427     http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
428              inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
429              c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
430 }
431
432 static void update_datarate(DataRateData *drd, int64_t count)
433 {
434     if (!drd->time1 && !drd->count1) {
435         drd->time1 = drd->time2 = cur_time;
436         drd->count1 = drd->count2 = count;
437     } else if (cur_time - drd->time2 > 5000) {
438         drd->time1 = drd->time2;
439         drd->count1 = drd->count2;
440         drd->time2 = cur_time;
441         drd->count2 = count;
442     }
443 }
444
445 /* In bytes per second */
446 static int compute_datarate(DataRateData *drd, int64_t count)
447 {
448     if (cur_time == drd->time1)
449         return 0;
450
451     return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
452 }
453
454
455 static void start_children(FFStream *feed)
456 {
457     if (no_launch)
458         return;
459
460     for (; feed; feed = feed->next) {
461         if (feed->child_argv && !feed->pid) {
462             feed->pid_start = time(0);
463
464             feed->pid = fork();
465
466             if (feed->pid < 0) {
467                 http_log("Unable to create children\n");
468                 exit(1);
469             }
470             if (!feed->pid) {
471                 /* In child */
472                 char pathname[1024];
473                 char *slash;
474                 int i;
475
476                 av_strlcpy(pathname, my_program_name, sizeof(pathname));
477
478                 slash = strrchr(pathname, '/');
479                 if (!slash)
480                     slash = pathname;
481                 else
482                     slash++;
483                 strcpy(slash, "ffmpeg");
484
485                 http_log("Launch command line: ");
486                 http_log("%s ", pathname);
487                 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
488                     http_log("%s ", feed->child_argv[i]);
489                 http_log("\n");
490
491                 for (i = 3; i < 256; i++)
492                     close(i);
493
494                 if (!ffserver_debug) {
495                     i = open("/dev/null", O_RDWR);
496                     if (i != -1) {
497                         dup2(i, 0);
498                         dup2(i, 1);
499                         dup2(i, 2);
500                         close(i);
501                     }
502                 }
503
504                 /* This is needed to make relative pathnames work */
505                 if (chdir(my_program_dir) < 0) {
506                     http_log("chdir failed\n");
507                     exit(1);
508                 }
509
510                 signal(SIGPIPE, SIG_DFL);
511
512                 execvp(pathname, feed->child_argv);
513
514                 _exit(1);
515             }
516         }
517     }
518 }
519
520 /* open a listening socket */
521 static int socket_open_listen(struct sockaddr_in *my_addr)
522 {
523     int server_fd, tmp;
524
525     server_fd = socket(AF_INET,SOCK_STREAM,0);
526     if (server_fd < 0) {
527         perror ("socket");
528         return -1;
529     }
530
531     tmp = 1;
532     setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
533
534     my_addr->sin_family = AF_INET;
535     if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
536         char bindmsg[32];
537         snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
538         perror (bindmsg);
539         closesocket(server_fd);
540         return -1;
541     }
542
543     if (listen (server_fd, 5) < 0) {
544         perror ("listen");
545         closesocket(server_fd);
546         return -1;
547     }
548     ff_socket_nonblock(server_fd, 1);
549
550     return server_fd;
551 }
552
553 /* start all multicast streams */
554 static void start_multicast(void)
555 {
556     FFStream *stream;
557     char session_id[32];
558     HTTPContext *rtp_c;
559     struct sockaddr_in dest_addr;
560     int default_port, stream_index;
561
562     default_port = 6000;
563     for(stream = first_stream; stream != NULL; stream = stream->next) {
564         if (stream->is_multicast) {
565             /* open the RTP connection */
566             snprintf(session_id, sizeof(session_id), "%08x%08x",
567                      av_lfg_get(&random_state), av_lfg_get(&random_state));
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     s->flags |= AVFMT_FLAG_GENPTS;
2165     c->fmt_in = s;
2166     if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2167         http_log("Could not find stream info '%s'\n", input_filename);
2168         avformat_close_input(&s);
2169         return -1;
2170     }
2171
2172     /* choose stream as clock source (we favorize video stream if
2173        present) for packet sending */
2174     c->pts_stream_index = 0;
2175     for(i=0;i<c->stream->nb_streams;i++) {
2176         if (c->pts_stream_index == 0 &&
2177             c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2178             c->pts_stream_index = i;
2179         }
2180     }
2181
2182     if (c->fmt_in->iformat->read_seek)
2183         av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2184     /* set the start time (needed for maxtime and RTP packet timing) */
2185     c->start_time = cur_time;
2186     c->first_pts = AV_NOPTS_VALUE;
2187     return 0;
2188 }
2189
2190 /* return the server clock (in us) */
2191 static int64_t get_server_clock(HTTPContext *c)
2192 {
2193     /* compute current pts value from system time */
2194     return (cur_time - c->start_time) * 1000;
2195 }
2196
2197 /* return the estimated time at which the current packet must be sent
2198    (in us) */
2199 static int64_t get_packet_send_clock(HTTPContext *c)
2200 {
2201     int bytes_left, bytes_sent, frame_bytes;
2202
2203     frame_bytes = c->cur_frame_bytes;
2204     if (frame_bytes <= 0)
2205         return c->cur_pts;
2206     else {
2207         bytes_left = c->buffer_end - c->buffer_ptr;
2208         bytes_sent = frame_bytes - bytes_left;
2209         return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2210     }
2211 }
2212
2213
2214 static int http_prepare_data(HTTPContext *c)
2215 {
2216     int i, len, ret;
2217     AVFormatContext *ctx;
2218
2219     av_freep(&c->pb_buffer);
2220     switch(c->state) {
2221     case HTTPSTATE_SEND_DATA_HEADER:
2222         memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2223         av_dict_set(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2224         av_dict_set(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2225         av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2226         av_dict_set(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2227
2228         c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2229
2230         for(i=0;i<c->stream->nb_streams;i++) {
2231             AVStream *src;
2232             c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2233             /* if file or feed, then just take streams from FFStream struct */
2234             if (!c->stream->feed ||
2235                 c->stream->feed == c->stream)
2236                 src = c->stream->streams[i];
2237             else
2238                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2239
2240             *(c->fmt_ctx.streams[i]) = *src;
2241             c->fmt_ctx.streams[i]->priv_data = 0;
2242             c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2243                                            AVStream, not in codec */
2244         }
2245         /* set output format parameters */
2246         c->fmt_ctx.oformat = c->stream->fmt;
2247         c->fmt_ctx.nb_streams = c->stream->nb_streams;
2248
2249         c->got_key_frame = 0;
2250
2251         /* prepare header and save header data in a stream */
2252         if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2253             /* XXX: potential leak */
2254             return -1;
2255         }
2256         c->fmt_ctx.pb->seekable = 0;
2257
2258         /*
2259          * HACK to avoid mpeg ps muxer to spit many underflow errors
2260          * Default value from FFmpeg
2261          * Try to set it use configuration option
2262          */
2263         c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2264
2265         if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2266             http_log("Error writing output header\n");
2267             return -1;
2268         }
2269         av_dict_free(&c->fmt_ctx.metadata);
2270
2271         len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2272         c->buffer_ptr = c->pb_buffer;
2273         c->buffer_end = c->pb_buffer + len;
2274
2275         c->state = HTTPSTATE_SEND_DATA;
2276         c->last_packet_sent = 0;
2277         break;
2278     case HTTPSTATE_SEND_DATA:
2279         /* find a new packet */
2280         /* read a packet from the input stream */
2281         if (c->stream->feed)
2282             ffm_set_write_index(c->fmt_in,
2283                                 c->stream->feed->feed_write_index,
2284                                 c->stream->feed->feed_size);
2285
2286         if (c->stream->max_time &&
2287             c->stream->max_time + c->start_time - cur_time < 0)
2288             /* We have timed out */
2289             c->state = HTTPSTATE_SEND_DATA_TRAILER;
2290         else {
2291             AVPacket pkt;
2292         redo:
2293             ret = av_read_frame(c->fmt_in, &pkt);
2294             if (ret < 0) {
2295                 if (c->stream->feed) {
2296                     /* if coming from feed, it means we reached the end of the
2297                        ffm file, so must wait for more data */
2298                     c->state = HTTPSTATE_WAIT_FEED;
2299                     return 1; /* state changed */
2300                 } else if (ret == AVERROR(EAGAIN)) {
2301                     /* input not ready, come back later */
2302                     return 0;
2303                 } else {
2304                     if (c->stream->loop) {
2305                         avformat_close_input(&c->fmt_in);
2306                         if (open_input_stream(c, "") < 0)
2307                             goto no_loop;
2308                         goto redo;
2309                     } else {
2310                     no_loop:
2311                         /* must send trailer now because eof or error */
2312                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2313                     }
2314                 }
2315             } else {
2316                 int source_index = pkt.stream_index;
2317                 /* update first pts if needed */
2318                 if (c->first_pts == AV_NOPTS_VALUE) {
2319                     c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2320                     c->start_time = cur_time;
2321                 }
2322                 /* send it to the appropriate stream */
2323                 if (c->stream->feed) {
2324                     /* if coming from a feed, select the right stream */
2325                     if (c->switch_pending) {
2326                         c->switch_pending = 0;
2327                         for(i=0;i<c->stream->nb_streams;i++) {
2328                             if (c->switch_feed_streams[i] == pkt.stream_index)
2329                                 if (pkt.flags & AV_PKT_FLAG_KEY)
2330                                     c->switch_feed_streams[i] = -1;
2331                             if (c->switch_feed_streams[i] >= 0)
2332                                 c->switch_pending = 1;
2333                         }
2334                     }
2335                     for(i=0;i<c->stream->nb_streams;i++) {
2336                         if (c->stream->feed_streams[i] == pkt.stream_index) {
2337                             AVStream *st = c->fmt_in->streams[source_index];
2338                             pkt.stream_index = i;
2339                             if (pkt.flags & AV_PKT_FLAG_KEY &&
2340                                 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2341                                  c->stream->nb_streams == 1))
2342                                 c->got_key_frame = 1;
2343                             if (!c->stream->send_on_key || c->got_key_frame)
2344                                 goto send_it;
2345                         }
2346                     }
2347                 } else {
2348                     AVCodecContext *codec;
2349                     AVStream *ist, *ost;
2350                 send_it:
2351                     ist = c->fmt_in->streams[source_index];
2352                     /* specific handling for RTP: we use several
2353                        output stream (one for each RTP
2354                        connection). XXX: need more abstract handling */
2355                     if (c->is_packetized) {
2356                         /* compute send time and duration */
2357                         c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2358                         c->cur_pts -= c->first_pts;
2359                         c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2360                         /* find RTP context */
2361                         c->packet_stream_index = pkt.stream_index;
2362                         ctx = c->rtp_ctx[c->packet_stream_index];
2363                         if(!ctx) {
2364                             av_free_packet(&pkt);
2365                             break;
2366                         }
2367                         codec = ctx->streams[0]->codec;
2368                         /* only one stream per RTP connection */
2369                         pkt.stream_index = 0;
2370                     } else {
2371                         ctx = &c->fmt_ctx;
2372                         /* Fudge here */
2373                         codec = ctx->streams[pkt.stream_index]->codec;
2374                     }
2375
2376                     if (c->is_packetized) {
2377                         int max_packet_size;
2378                         if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2379                             max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2380                         else
2381                             max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2382                         ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2383                     } else {
2384                         ret = avio_open_dyn_buf(&ctx->pb);
2385                     }
2386                     if (ret < 0) {
2387                         /* XXX: potential leak */
2388                         return -1;
2389                     }
2390                     ost = ctx->streams[pkt.stream_index];
2391
2392                     ctx->pb->seekable = 0;
2393                     if (pkt.dts != AV_NOPTS_VALUE)
2394                         pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2395                     if (pkt.pts != AV_NOPTS_VALUE)
2396                         pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2397                     pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2398                     if (av_write_frame(ctx, &pkt) < 0) {
2399                         http_log("Error writing frame to output\n");
2400                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2401                     }
2402
2403                     len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2404                     c->cur_frame_bytes = len;
2405                     c->buffer_ptr = c->pb_buffer;
2406                     c->buffer_end = c->pb_buffer + len;
2407
2408                     codec->frame_number++;
2409                     if (len == 0) {
2410                         av_free_packet(&pkt);
2411                         goto redo;
2412                     }
2413                 }
2414                 av_free_packet(&pkt);
2415             }
2416         }
2417         break;
2418     default:
2419     case HTTPSTATE_SEND_DATA_TRAILER:
2420         /* last packet test ? */
2421         if (c->last_packet_sent || c->is_packetized)
2422             return -1;
2423         ctx = &c->fmt_ctx;
2424         /* prepare header */
2425         if (avio_open_dyn_buf(&ctx->pb) < 0) {
2426             /* XXX: potential leak */
2427             return -1;
2428         }
2429         c->fmt_ctx.pb->seekable = 0;
2430         av_write_trailer(ctx);
2431         len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2432         c->buffer_ptr = c->pb_buffer;
2433         c->buffer_end = c->pb_buffer + len;
2434
2435         c->last_packet_sent = 1;
2436         break;
2437     }
2438     return 0;
2439 }
2440
2441 /* should convert the format at the same time */
2442 /* send data starting at c->buffer_ptr to the output connection
2443    (either UDP or TCP connection) */
2444 static int http_send_data(HTTPContext *c)
2445 {
2446     int len, ret;
2447
2448     for(;;) {
2449         if (c->buffer_ptr >= c->buffer_end) {
2450             ret = http_prepare_data(c);
2451             if (ret < 0)
2452                 return -1;
2453             else if (ret != 0)
2454                 /* state change requested */
2455                 break;
2456         } else {
2457             if (c->is_packetized) {
2458                 /* RTP data output */
2459                 len = c->buffer_end - c->buffer_ptr;
2460                 if (len < 4) {
2461                     /* fail safe - should never happen */
2462                 fail1:
2463                     c->buffer_ptr = c->buffer_end;
2464                     return 0;
2465                 }
2466                 len = (c->buffer_ptr[0] << 24) |
2467                     (c->buffer_ptr[1] << 16) |
2468                     (c->buffer_ptr[2] << 8) |
2469                     (c->buffer_ptr[3]);
2470                 if (len > (c->buffer_end - c->buffer_ptr))
2471                     goto fail1;
2472                 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2473                     /* nothing to send yet: we can wait */
2474                     return 0;
2475                 }
2476
2477                 c->data_count += len;
2478                 update_datarate(&c->datarate, c->data_count);
2479                 if (c->stream)
2480                     c->stream->bytes_served += len;
2481
2482                 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2483                     /* RTP packets are sent inside the RTSP TCP connection */
2484                     AVIOContext *pb;
2485                     int interleaved_index, size;
2486                     uint8_t header[4];
2487                     HTTPContext *rtsp_c;
2488
2489                     rtsp_c = c->rtsp_c;
2490                     /* if no RTSP connection left, error */
2491                     if (!rtsp_c)
2492                         return -1;
2493                     /* if already sending something, then wait. */
2494                     if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2495                         break;
2496                     if (avio_open_dyn_buf(&pb) < 0)
2497                         goto fail1;
2498                     interleaved_index = c->packet_stream_index * 2;
2499                     /* RTCP packets are sent at odd indexes */
2500                     if (c->buffer_ptr[1] == 200)
2501                         interleaved_index++;
2502                     /* write RTSP TCP header */
2503                     header[0] = '$';
2504                     header[1] = interleaved_index;
2505                     header[2] = len >> 8;
2506                     header[3] = len;
2507                     avio_write(pb, header, 4);
2508                     /* write RTP packet data */
2509                     c->buffer_ptr += 4;
2510                     avio_write(pb, c->buffer_ptr, len);
2511                     size = avio_close_dyn_buf(pb, &c->packet_buffer);
2512                     /* prepare asynchronous TCP sending */
2513                     rtsp_c->packet_buffer_ptr = c->packet_buffer;
2514                     rtsp_c->packet_buffer_end = c->packet_buffer + size;
2515                     c->buffer_ptr += len;
2516
2517                     /* send everything we can NOW */
2518                     len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2519                                 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2520                     if (len > 0)
2521                         rtsp_c->packet_buffer_ptr += len;
2522                     if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2523                         /* if we could not send all the data, we will
2524                            send it later, so a new state is needed to
2525                            "lock" the RTSP TCP connection */
2526                         rtsp_c->state = RTSPSTATE_SEND_PACKET;
2527                         break;
2528                     } else
2529                         /* all data has been sent */
2530                         av_freep(&c->packet_buffer);
2531                 } else {
2532                     /* send RTP packet directly in UDP */
2533                     c->buffer_ptr += 4;
2534                     ffurl_write(c->rtp_handles[c->packet_stream_index],
2535                                 c->buffer_ptr, len);
2536                     c->buffer_ptr += len;
2537                     /* here we continue as we can send several packets per 10 ms slot */
2538                 }
2539             } else {
2540                 /* TCP data output */
2541                 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2542                 if (len < 0) {
2543                     if (ff_neterrno() != AVERROR(EAGAIN) &&
2544                         ff_neterrno() != AVERROR(EINTR))
2545                         /* error : close connection */
2546                         return -1;
2547                     else
2548                         return 0;
2549                 } else
2550                     c->buffer_ptr += len;
2551
2552                 c->data_count += len;
2553                 update_datarate(&c->datarate, c->data_count);
2554                 if (c->stream)
2555                     c->stream->bytes_served += len;
2556                 break;
2557             }
2558         }
2559     } /* for(;;) */
2560     return 0;
2561 }
2562
2563 static int http_start_receive_data(HTTPContext *c)
2564 {
2565     int fd;
2566
2567     if (c->stream->feed_opened)
2568         return -1;
2569
2570     /* Don't permit writing to this one */
2571     if (c->stream->readonly)
2572         return -1;
2573
2574     /* open feed */
2575     fd = open(c->stream->feed_filename, O_RDWR);
2576     if (fd < 0) {
2577         http_log("Error opening feeder file: %s\n", strerror(errno));
2578         return -1;
2579     }
2580     c->feed_fd = fd;
2581
2582     if (c->stream->truncate) {
2583         /* truncate feed file */
2584         ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2585         ftruncate(c->feed_fd, FFM_PACKET_SIZE);
2586         http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2587     } else {
2588         if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2589             http_log("Error reading write index from feed file: %s\n", strerror(errno));
2590             return -1;
2591         }
2592     }
2593
2594     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2595     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2596     lseek(fd, 0, SEEK_SET);
2597
2598     /* init buffer input */
2599     c->buffer_ptr = c->buffer;
2600     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2601     c->stream->feed_opened = 1;
2602     c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2603     return 0;
2604 }
2605
2606 static int http_receive_data(HTTPContext *c)
2607 {
2608     HTTPContext *c1;
2609     int len, loop_run = 0;
2610
2611     while (c->chunked_encoding && !c->chunk_size &&
2612            c->buffer_end > c->buffer_ptr) {
2613         /* read chunk header, if present */
2614         len = recv(c->fd, c->buffer_ptr, 1, 0);
2615
2616         if (len < 0) {
2617             if (ff_neterrno() != AVERROR(EAGAIN) &&
2618                 ff_neterrno() != AVERROR(EINTR))
2619                 /* error : close connection */
2620                 goto fail;
2621             return 0;
2622         } else if (len == 0) {
2623             /* end of connection : close it */
2624             goto fail;
2625         } else if (c->buffer_ptr - c->buffer >= 2 &&
2626                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2627             c->chunk_size = strtol(c->buffer, 0, 16);
2628             if (c->chunk_size == 0) // end of stream
2629                 goto fail;
2630             c->buffer_ptr = c->buffer;
2631             break;
2632         } else if (++loop_run > 10) {
2633             /* no chunk header, abort */
2634             goto fail;
2635         } else {
2636             c->buffer_ptr++;
2637         }
2638     }
2639
2640     if (c->buffer_end > c->buffer_ptr) {
2641         len = recv(c->fd, c->buffer_ptr,
2642                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2643         if (len < 0) {
2644             if (ff_neterrno() != AVERROR(EAGAIN) &&
2645                 ff_neterrno() != AVERROR(EINTR))
2646                 /* error : close connection */
2647                 goto fail;
2648         } else if (len == 0)
2649             /* end of connection : close it */
2650             goto fail;
2651         else {
2652             c->chunk_size -= len;
2653             c->buffer_ptr += len;
2654             c->data_count += len;
2655             update_datarate(&c->datarate, c->data_count);
2656         }
2657     }
2658
2659     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2660         if (c->buffer[0] != 'f' ||
2661             c->buffer[1] != 'm') {
2662             http_log("Feed stream has become desynchronized -- disconnecting\n");
2663             goto fail;
2664         }
2665     }
2666
2667     if (c->buffer_ptr >= c->buffer_end) {
2668         FFStream *feed = c->stream;
2669         /* a packet has been received : write it in the store, except
2670            if header */
2671         if (c->data_count > FFM_PACKET_SIZE) {
2672
2673             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2674             /* XXX: use llseek or url_seek */
2675             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2676             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2677                 http_log("Error writing to feed file: %s\n", strerror(errno));
2678                 goto fail;
2679             }
2680
2681             feed->feed_write_index += FFM_PACKET_SIZE;
2682             /* update file size */
2683             if (feed->feed_write_index > c->stream->feed_size)
2684                 feed->feed_size = feed->feed_write_index;
2685
2686             /* handle wrap around if max file size reached */
2687             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2688                 feed->feed_write_index = FFM_PACKET_SIZE;
2689
2690             /* write index */
2691             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2692                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2693                 goto fail;
2694             }
2695
2696             /* wake up any waiting connections */
2697             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2698                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2699                     c1->stream->feed == c->stream->feed)
2700                     c1->state = HTTPSTATE_SEND_DATA;
2701             }
2702         } else {
2703             /* We have a header in our hands that contains useful data */
2704             AVFormatContext *s = avformat_alloc_context();
2705             AVIOContext *pb;
2706             AVInputFormat *fmt_in;
2707             int i;
2708
2709             if (!s)
2710                 goto fail;
2711
2712             /* use feed output format name to find corresponding input format */
2713             fmt_in = av_find_input_format(feed->fmt->name);
2714             if (!fmt_in)
2715                 goto fail;
2716
2717             pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2718                                     0, NULL, NULL, NULL, NULL);
2719             pb->seekable = 0;
2720
2721             s->pb = pb;
2722             if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2723                 av_free(pb);
2724                 goto fail;
2725             }
2726
2727             /* Now we have the actual streams */
2728             if (s->nb_streams != feed->nb_streams) {
2729                 avformat_close_input(&s);
2730                 av_free(pb);
2731                 http_log("Feed '%s' stream number does not match registered feed\n",
2732                          c->stream->feed_filename);
2733                 goto fail;
2734             }
2735
2736             for (i = 0; i < s->nb_streams; i++) {
2737                 AVStream *fst = feed->streams[i];
2738                 AVStream *st = s->streams[i];
2739                 avcodec_copy_context(fst->codec, st->codec);
2740             }
2741
2742             avformat_close_input(&s);
2743             av_free(pb);
2744         }
2745         c->buffer_ptr = c->buffer;
2746     }
2747
2748     return 0;
2749  fail:
2750     c->stream->feed_opened = 0;
2751     close(c->feed_fd);
2752     /* wake up any waiting connections to stop waiting for feed */
2753     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2754         if (c1->state == HTTPSTATE_WAIT_FEED &&
2755             c1->stream->feed == c->stream->feed)
2756             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2757     }
2758     return -1;
2759 }
2760
2761 /********************************************************************/
2762 /* RTSP handling */
2763
2764 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2765 {
2766     const char *str;
2767     time_t ti;
2768     struct tm *tm;
2769     char buf2[32];
2770
2771     switch(error_number) {
2772     case RTSP_STATUS_OK:
2773         str = "OK";
2774         break;
2775     case RTSP_STATUS_METHOD:
2776         str = "Method Not Allowed";
2777         break;
2778     case RTSP_STATUS_BANDWIDTH:
2779         str = "Not Enough Bandwidth";
2780         break;
2781     case RTSP_STATUS_SESSION:
2782         str = "Session Not Found";
2783         break;
2784     case RTSP_STATUS_STATE:
2785         str = "Method Not Valid in This State";
2786         break;
2787     case RTSP_STATUS_AGGREGATE:
2788         str = "Aggregate operation not allowed";
2789         break;
2790     case RTSP_STATUS_ONLY_AGGREGATE:
2791         str = "Only aggregate operation allowed";
2792         break;
2793     case RTSP_STATUS_TRANSPORT:
2794         str = "Unsupported transport";
2795         break;
2796     case RTSP_STATUS_INTERNAL:
2797         str = "Internal Server Error";
2798         break;
2799     case RTSP_STATUS_SERVICE:
2800         str = "Service Unavailable";
2801         break;
2802     case RTSP_STATUS_VERSION:
2803         str = "RTSP Version not supported";
2804         break;
2805     default:
2806         str = "Unknown Error";
2807         break;
2808     }
2809
2810     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2811     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2812
2813     /* output GMT time */
2814     ti = time(NULL);
2815     tm = gmtime(&ti);
2816     strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2817     avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2818 }
2819
2820 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2821 {
2822     rtsp_reply_header(c, error_number);
2823     avio_printf(c->pb, "\r\n");
2824 }
2825
2826 static int rtsp_parse_request(HTTPContext *c)
2827 {
2828     const char *p, *p1, *p2;
2829     char cmd[32];
2830     char url[1024];
2831     char protocol[32];
2832     char line[1024];
2833     int len;
2834     RTSPMessageHeader header1, *header = &header1;
2835
2836     c->buffer_ptr[0] = '\0';
2837     p = c->buffer;
2838
2839     get_word(cmd, sizeof(cmd), &p);
2840     get_word(url, sizeof(url), &p);
2841     get_word(protocol, sizeof(protocol), &p);
2842
2843     av_strlcpy(c->method, cmd, sizeof(c->method));
2844     av_strlcpy(c->url, url, sizeof(c->url));
2845     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2846
2847     if (avio_open_dyn_buf(&c->pb) < 0) {
2848         /* XXX: cannot do more */
2849         c->pb = NULL; /* safety */
2850         return -1;
2851     }
2852
2853     /* check version name */
2854     if (strcmp(protocol, "RTSP/1.0") != 0) {
2855         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2856         goto the_end;
2857     }
2858
2859     /* parse each header line */
2860     memset(header, 0, sizeof(*header));
2861     /* skip to next line */
2862     while (*p != '\n' && *p != '\0')
2863         p++;
2864     if (*p == '\n')
2865         p++;
2866     while (*p != '\0') {
2867         p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2868         if (!p1)
2869             break;
2870         p2 = p1;
2871         if (p2 > p && p2[-1] == '\r')
2872             p2--;
2873         /* skip empty line */
2874         if (p2 == p)
2875             break;
2876         len = p2 - p;
2877         if (len > sizeof(line) - 1)
2878             len = sizeof(line) - 1;
2879         memcpy(line, p, len);
2880         line[len] = '\0';
2881         ff_rtsp_parse_line(header, line, NULL, NULL);
2882         p = p1 + 1;
2883     }
2884
2885     /* handle sequence number */
2886     c->seq = header->seq;
2887
2888     if (!strcmp(cmd, "DESCRIBE"))
2889         rtsp_cmd_describe(c, url);
2890     else if (!strcmp(cmd, "OPTIONS"))
2891         rtsp_cmd_options(c, url);
2892     else if (!strcmp(cmd, "SETUP"))
2893         rtsp_cmd_setup(c, url, header);
2894     else if (!strcmp(cmd, "PLAY"))
2895         rtsp_cmd_play(c, url, header);
2896     else if (!strcmp(cmd, "PAUSE"))
2897         rtsp_cmd_pause(c, url, header);
2898     else if (!strcmp(cmd, "TEARDOWN"))
2899         rtsp_cmd_teardown(c, url, header);
2900     else
2901         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2902
2903  the_end:
2904     len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2905     c->pb = NULL; /* safety */
2906     if (len < 0) {
2907         /* XXX: cannot do more */
2908         return -1;
2909     }
2910     c->buffer_ptr = c->pb_buffer;
2911     c->buffer_end = c->pb_buffer + len;
2912     c->state = RTSPSTATE_SEND_REPLY;
2913     return 0;
2914 }
2915
2916 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2917                                    struct in_addr my_ip)
2918 {
2919     AVFormatContext *avc;
2920     AVStream *avs = NULL;
2921     int i;
2922
2923     avc =  avformat_alloc_context();
2924     if (avc == NULL) {
2925         return -1;
2926     }
2927     av_dict_set(&avc->metadata, "title",
2928                stream->title[0] ? stream->title : "No Title", 0);
2929     avc->nb_streams = stream->nb_streams;
2930     if (stream->is_multicast) {
2931         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2932                  inet_ntoa(stream->multicast_ip),
2933                  stream->multicast_port, stream->multicast_ttl);
2934     } else {
2935         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2936     }
2937
2938     if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2939         !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2940         goto sdp_done;
2941     if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2942         !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2943         goto sdp_done;
2944
2945     for(i = 0; i < stream->nb_streams; i++) {
2946         avc->streams[i] = &avs[i];
2947         avc->streams[i]->codec = stream->streams[i]->codec;
2948     }
2949     *pbuffer = av_mallocz(2048);
2950     av_sdp_create(&avc, 1, *pbuffer, 2048);
2951
2952  sdp_done:
2953     av_free(avc->streams);
2954     av_dict_free(&avc->metadata);
2955     av_free(avc);
2956     av_free(avs);
2957
2958     return strlen(*pbuffer);
2959 }
2960
2961 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2962 {
2963 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2964     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2965     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2966     avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2967     avio_printf(c->pb, "\r\n");
2968 }
2969
2970 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2971 {
2972     FFStream *stream;
2973     char path1[1024];
2974     const char *path;
2975     uint8_t *content;
2976     int content_length, len;
2977     struct sockaddr_in my_addr;
2978
2979     /* find which url is asked */
2980     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2981     path = path1;
2982     if (*path == '/')
2983         path++;
2984
2985     for(stream = first_stream; stream != NULL; stream = stream->next) {
2986         if (!stream->is_feed &&
2987             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2988             !strcmp(path, stream->filename)) {
2989             goto found;
2990         }
2991     }
2992     /* no stream found */
2993     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2994     return;
2995
2996  found:
2997     /* prepare the media description in sdp format */
2998
2999     /* get the host IP */
3000     len = sizeof(my_addr);
3001     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3002     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3003     if (content_length < 0) {
3004         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3005         return;
3006     }
3007     rtsp_reply_header(c, RTSP_STATUS_OK);
3008     avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3009     avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3010     avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3011     avio_printf(c->pb, "\r\n");
3012     avio_write(c->pb, content, content_length);
3013     av_free(content);
3014 }
3015
3016 static HTTPContext *find_rtp_session(const char *session_id)
3017 {
3018     HTTPContext *c;
3019
3020     if (session_id[0] == '\0')
3021         return NULL;
3022
3023     for(c = first_http_ctx; c != NULL; c = c->next) {
3024         if (!strcmp(c->session_id, session_id))
3025             return c;
3026     }
3027     return NULL;
3028 }
3029
3030 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3031 {
3032     RTSPTransportField *th;
3033     int i;
3034
3035     for(i=0;i<h->nb_transports;i++) {
3036         th = &h->transports[i];
3037         if (th->lower_transport == lower_transport)
3038             return th;
3039     }
3040     return NULL;
3041 }
3042
3043 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3044                            RTSPMessageHeader *h)
3045 {
3046     FFStream *stream;
3047     int stream_index, rtp_port, rtcp_port;
3048     char buf[1024];
3049     char path1[1024];
3050     const char *path;
3051     HTTPContext *rtp_c;
3052     RTSPTransportField *th;
3053     struct sockaddr_in dest_addr;
3054     RTSPActionServerSetup setup;
3055
3056     /* find which url is asked */
3057     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3058     path = path1;
3059     if (*path == '/')
3060         path++;
3061
3062     /* now check each stream */
3063     for(stream = first_stream; stream != NULL; stream = stream->next) {
3064         if (!stream->is_feed &&
3065             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3066             /* accept aggregate filenames only if single stream */
3067             if (!strcmp(path, stream->filename)) {
3068                 if (stream->nb_streams != 1) {
3069                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3070                     return;
3071                 }
3072                 stream_index = 0;
3073                 goto found;
3074             }
3075
3076             for(stream_index = 0; stream_index < stream->nb_streams;
3077                 stream_index++) {
3078                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3079                          stream->filename, stream_index);
3080                 if (!strcmp(path, buf))
3081                     goto found;
3082             }
3083         }
3084     }
3085     /* no stream found */
3086     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3087     return;
3088  found:
3089
3090     /* generate session id if needed */
3091     if (h->session_id[0] == '\0')
3092         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3093                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3094
3095     /* find rtp session, and create it if none found */
3096     rtp_c = find_rtp_session(h->session_id);
3097     if (!rtp_c) {
3098         /* always prefer UDP */
3099         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3100         if (!th) {
3101             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3102             if (!th) {
3103                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3104                 return;
3105             }
3106         }
3107
3108         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3109                                    th->lower_transport);
3110         if (!rtp_c) {
3111             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3112             return;
3113         }
3114
3115         /* open input stream */
3116         if (open_input_stream(rtp_c, "") < 0) {
3117             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3118             return;
3119         }
3120     }
3121
3122     /* test if stream is OK (test needed because several SETUP needs
3123        to be done for a given file) */
3124     if (rtp_c->stream != stream) {
3125         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3126         return;
3127     }
3128
3129     /* test if stream is already set up */
3130     if (rtp_c->rtp_ctx[stream_index]) {
3131         rtsp_reply_error(c, RTSP_STATUS_STATE);
3132         return;
3133     }
3134
3135     /* check transport */
3136     th = find_transport(h, rtp_c->rtp_protocol);
3137     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3138                 th->client_port_min <= 0)) {
3139         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3140         return;
3141     }
3142
3143     /* setup default options */
3144     setup.transport_option[0] = '\0';
3145     dest_addr = rtp_c->from_addr;
3146     dest_addr.sin_port = htons(th->client_port_min);
3147
3148     /* setup stream */
3149     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3150         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3151         return;
3152     }
3153
3154     /* now everything is OK, so we can send the connection parameters */
3155     rtsp_reply_header(c, RTSP_STATUS_OK);
3156     /* session ID */
3157     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3158
3159     switch(rtp_c->rtp_protocol) {
3160     case RTSP_LOWER_TRANSPORT_UDP:
3161         rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3162         rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3163         avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3164                     "client_port=%d-%d;server_port=%d-%d",
3165                     th->client_port_min, th->client_port_max,
3166                     rtp_port, rtcp_port);
3167         break;
3168     case RTSP_LOWER_TRANSPORT_TCP:
3169         avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3170                     stream_index * 2, stream_index * 2 + 1);
3171         break;
3172     default:
3173         break;
3174     }
3175     if (setup.transport_option[0] != '\0')
3176         avio_printf(c->pb, ";%s", setup.transport_option);
3177     avio_printf(c->pb, "\r\n");
3178
3179
3180     avio_printf(c->pb, "\r\n");
3181 }
3182
3183
3184 /* find an rtp connection by using the session ID. Check consistency
3185    with filename */
3186 static HTTPContext *find_rtp_session_with_url(const char *url,
3187                                               const char *session_id)
3188 {
3189     HTTPContext *rtp_c;
3190     char path1[1024];
3191     const char *path;
3192     char buf[1024];
3193     int s, len;
3194
3195     rtp_c = find_rtp_session(session_id);
3196     if (!rtp_c)
3197         return NULL;
3198
3199     /* find which url is asked */
3200     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3201     path = path1;
3202     if (*path == '/')
3203         path++;
3204     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3205     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3206       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3207         rtp_c->stream->filename, s);
3208       if(!strncmp(path, buf, sizeof(buf))) {
3209     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3210         return rtp_c;
3211       }
3212     }
3213     len = strlen(path);
3214     if (len > 0 && path[len - 1] == '/' &&
3215         !strncmp(path, rtp_c->stream->filename, len - 1))
3216         return rtp_c;
3217     return NULL;
3218 }
3219
3220 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3221 {
3222     HTTPContext *rtp_c;
3223
3224     rtp_c = find_rtp_session_with_url(url, h->session_id);
3225     if (!rtp_c) {
3226         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3227         return;
3228     }
3229
3230     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3231         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3232         rtp_c->state != HTTPSTATE_READY) {
3233         rtsp_reply_error(c, RTSP_STATUS_STATE);
3234         return;
3235     }
3236
3237     rtp_c->state = HTTPSTATE_SEND_DATA;
3238
3239     /* now everything is OK, so we can send the connection parameters */
3240     rtsp_reply_header(c, RTSP_STATUS_OK);
3241     /* session ID */
3242     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3243     avio_printf(c->pb, "\r\n");
3244 }
3245
3246 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3247 {
3248     HTTPContext *rtp_c;
3249
3250     rtp_c = find_rtp_session_with_url(url, h->session_id);
3251     if (!rtp_c) {
3252         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3253         return;
3254     }
3255
3256     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3257         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3258         rtsp_reply_error(c, RTSP_STATUS_STATE);
3259         return;
3260     }
3261
3262     rtp_c->state = HTTPSTATE_READY;
3263     rtp_c->first_pts = AV_NOPTS_VALUE;
3264     /* now everything is OK, so we can send the connection parameters */
3265     rtsp_reply_header(c, RTSP_STATUS_OK);
3266     /* session ID */
3267     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3268     avio_printf(c->pb, "\r\n");
3269 }
3270
3271 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3272 {
3273     HTTPContext *rtp_c;
3274
3275     rtp_c = find_rtp_session_with_url(url, h->session_id);
3276     if (!rtp_c) {
3277         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3278         return;
3279     }
3280
3281     /* now everything is OK, so we can send the connection parameters */
3282     rtsp_reply_header(c, RTSP_STATUS_OK);
3283     /* session ID */
3284     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3285     avio_printf(c->pb, "\r\n");
3286
3287     /* abort the session */
3288     close_connection(rtp_c);
3289 }
3290
3291
3292 /********************************************************************/
3293 /* RTP handling */
3294
3295 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3296                                        FFStream *stream, const char *session_id,
3297                                        enum RTSPLowerTransport rtp_protocol)
3298 {
3299     HTTPContext *c = NULL;
3300     const char *proto_str;
3301
3302     /* XXX: should output a warning page when coming
3303        close to the connection limit */
3304     if (nb_connections >= nb_max_connections)
3305         goto fail;
3306
3307     /* add a new connection */
3308     c = av_mallocz(sizeof(HTTPContext));
3309     if (!c)
3310         goto fail;
3311
3312     c->fd = -1;
3313     c->poll_entry = NULL;
3314     c->from_addr = *from_addr;
3315     c->buffer_size = IOBUFFER_INIT_SIZE;
3316     c->buffer = av_malloc(c->buffer_size);
3317     if (!c->buffer)
3318         goto fail;
3319     nb_connections++;
3320     c->stream = stream;
3321     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3322     c->state = HTTPSTATE_READY;
3323     c->is_packetized = 1;
3324     c->rtp_protocol = rtp_protocol;
3325
3326     /* protocol is shown in statistics */
3327     switch(c->rtp_protocol) {
3328     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3329         proto_str = "MCAST";
3330         break;
3331     case RTSP_LOWER_TRANSPORT_UDP:
3332         proto_str = "UDP";
3333         break;
3334     case RTSP_LOWER_TRANSPORT_TCP:
3335         proto_str = "TCP";
3336         break;
3337     default:
3338         proto_str = "???";
3339         break;
3340     }
3341     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3342     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3343
3344     current_bandwidth += stream->bandwidth;
3345
3346     c->next = first_http_ctx;
3347     first_http_ctx = c;
3348     return c;
3349
3350  fail:
3351     if (c) {
3352         av_free(c->buffer);
3353         av_free(c);
3354     }
3355     return NULL;
3356 }
3357
3358 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3359    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3360    used. */
3361 static int rtp_new_av_stream(HTTPContext *c,
3362                              int stream_index, struct sockaddr_in *dest_addr,
3363                              HTTPContext *rtsp_c)
3364 {
3365     AVFormatContext *ctx;
3366     AVStream *st;
3367     char *ipaddr;
3368     URLContext *h = NULL;
3369     uint8_t *dummy_buf;
3370     int max_packet_size;
3371
3372     /* now we can open the relevant output stream */
3373     ctx = avformat_alloc_context();
3374     if (!ctx)
3375         return -1;
3376     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3377
3378     st = av_mallocz(sizeof(AVStream));
3379     if (!st)
3380         goto fail;
3381     ctx->nb_streams = 1;
3382     ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3383     if (!ctx->streams)
3384       goto fail;
3385     ctx->streams[0] = st;
3386
3387     if (!c->stream->feed ||
3388         c->stream->feed == c->stream)
3389         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3390     else
3391         memcpy(st,
3392                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3393                sizeof(AVStream));
3394     st->priv_data = NULL;
3395
3396     /* build destination RTP address */
3397     ipaddr = inet_ntoa(dest_addr->sin_addr);
3398
3399     switch(c->rtp_protocol) {
3400     case RTSP_LOWER_TRANSPORT_UDP:
3401     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3402         /* RTP/UDP case */
3403
3404         /* XXX: also pass as parameter to function ? */
3405         if (c->stream->is_multicast) {
3406             int ttl;
3407             ttl = c->stream->multicast_ttl;
3408             if (!ttl)
3409                 ttl = 16;
3410             snprintf(ctx->filename, sizeof(ctx->filename),
3411                      "rtp://%s:%d?multicast=1&ttl=%d",
3412                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3413         } else {
3414             snprintf(ctx->filename, sizeof(ctx->filename),
3415                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3416         }
3417
3418         if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3419             goto fail;
3420         c->rtp_handles[stream_index] = h;
3421         max_packet_size = h->max_packet_size;
3422         break;
3423     case RTSP_LOWER_TRANSPORT_TCP:
3424         /* RTP/TCP case */
3425         c->rtsp_c = rtsp_c;
3426         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3427         break;
3428     default:
3429         goto fail;
3430     }
3431
3432     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3433              ipaddr, ntohs(dest_addr->sin_port),
3434              c->stream->filename, stream_index, c->protocol);
3435
3436     /* normally, no packets should be output here, but the packet size may be checked */
3437     if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3438         /* XXX: close stream */
3439         goto fail;
3440     }
3441     if (avformat_write_header(ctx, NULL) < 0) {
3442     fail:
3443         if (h)
3444             ffurl_close(h);
3445         av_free(ctx);
3446         return -1;
3447     }
3448     avio_close_dyn_buf(ctx->pb, &dummy_buf);
3449     av_free(dummy_buf);
3450
3451     c->rtp_ctx[stream_index] = ctx;
3452     return 0;
3453 }
3454
3455 /********************************************************************/
3456 /* ffserver initialization */
3457
3458 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3459 {
3460     AVStream *fst;
3461
3462     fst = av_mallocz(sizeof(AVStream));
3463     if (!fst)
3464         return NULL;
3465     if (copy) {
3466         fst->codec = avcodec_alloc_context3(NULL);
3467         memcpy(fst->codec, codec, sizeof(AVCodecContext));
3468         if (codec->extradata_size) {
3469             fst->codec->extradata = av_malloc(codec->extradata_size);
3470             memcpy(fst->codec->extradata, codec->extradata,
3471                 codec->extradata_size);
3472         }
3473     } else {
3474         /* live streams must use the actual feed's codec since it may be
3475          * updated later to carry extradata needed by the streams.
3476          */
3477         fst->codec = codec;
3478     }
3479     fst->priv_data = av_mallocz(sizeof(FeedData));
3480     fst->index = stream->nb_streams;
3481     avpriv_set_pts_info(fst, 33, 1, 90000);
3482     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3483     stream->streams[stream->nb_streams++] = fst;
3484     return fst;
3485 }
3486
3487 /* return the stream number in the feed */
3488 static int add_av_stream(FFStream *feed, AVStream *st)
3489 {
3490     AVStream *fst;
3491     AVCodecContext *av, *av1;
3492     int i;
3493
3494     av = st->codec;
3495     for(i=0;i<feed->nb_streams;i++) {
3496         st = feed->streams[i];
3497         av1 = st->codec;
3498         if (av1->codec_id == av->codec_id &&
3499             av1->codec_type == av->codec_type &&
3500             av1->bit_rate == av->bit_rate) {
3501
3502             switch(av->codec_type) {
3503             case AVMEDIA_TYPE_AUDIO:
3504                 if (av1->channels == av->channels &&
3505                     av1->sample_rate == av->sample_rate)
3506                     return i;
3507                 break;
3508             case AVMEDIA_TYPE_VIDEO:
3509                 if (av1->width == av->width &&
3510                     av1->height == av->height &&
3511                     av1->time_base.den == av->time_base.den &&
3512                     av1->time_base.num == av->time_base.num &&
3513                     av1->gop_size == av->gop_size)
3514                     return i;
3515                 break;
3516             default:
3517                 abort();
3518             }
3519         }
3520     }
3521
3522     fst = add_av_stream1(feed, av, 0);
3523     if (!fst)
3524         return -1;
3525     return feed->nb_streams - 1;
3526 }
3527
3528 static void remove_stream(FFStream *stream)
3529 {
3530     FFStream **ps;
3531     ps = &first_stream;
3532     while (*ps != NULL) {
3533         if (*ps == stream)
3534             *ps = (*ps)->next;
3535         else
3536             ps = &(*ps)->next;
3537     }
3538 }
3539
3540 /* specific mpeg4 handling : we extract the raw parameters */
3541 static void extract_mpeg4_header(AVFormatContext *infile)
3542 {
3543     int mpeg4_count, i, size;
3544     AVPacket pkt;
3545     AVStream *st;
3546     const uint8_t *p;
3547
3548     mpeg4_count = 0;
3549     for(i=0;i<infile->nb_streams;i++) {
3550         st = infile->streams[i];
3551         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3552             st->codec->extradata_size == 0) {
3553             mpeg4_count++;
3554         }
3555     }
3556     if (!mpeg4_count)
3557         return;
3558
3559     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3560     while (mpeg4_count > 0) {
3561         if (av_read_packet(infile, &pkt) < 0)
3562             break;
3563         st = infile->streams[pkt.stream_index];
3564         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3565             st->codec->extradata_size == 0) {
3566             av_freep(&st->codec->extradata);
3567             /* fill extradata with the header */
3568             /* XXX: we make hard suppositions here ! */
3569             p = pkt.data;
3570             while (p < pkt.data + pkt.size - 4) {
3571                 /* stop when vop header is found */
3572                 if (p[0] == 0x00 && p[1] == 0x00 &&
3573                     p[2] == 0x01 && p[3] == 0xb6) {
3574                     size = p - pkt.data;
3575                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3576                     st->codec->extradata = av_malloc(size);
3577                     st->codec->extradata_size = size;
3578                     memcpy(st->codec->extradata, pkt.data, size);
3579                     break;
3580                 }
3581                 p++;
3582             }
3583             mpeg4_count--;
3584         }
3585         av_free_packet(&pkt);
3586     }
3587 }
3588
3589 /* compute the needed AVStream for each file */
3590 static void build_file_streams(void)
3591 {
3592     FFStream *stream, *stream_next;
3593     int i, ret;
3594
3595     /* gather all streams */
3596     for(stream = first_stream; stream != NULL; stream = stream_next) {
3597         AVFormatContext *infile = NULL;
3598         stream_next = stream->next;
3599         if (stream->stream_type == STREAM_TYPE_LIVE &&
3600             !stream->feed) {
3601             /* the stream comes from a file */
3602             /* try to open the file */
3603             /* open stream */
3604             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3605                 /* specific case : if transport stream output to RTP,
3606                    we use a raw transport stream reader */
3607                 av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3608             }
3609
3610             http_log("Opening file '%s'\n", stream->feed_filename);
3611             if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3612                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3613                 /* remove stream (no need to spend more time on it) */
3614             fail:
3615                 remove_stream(stream);
3616             } else {
3617                 /* find all the AVStreams inside and reference them in
3618                    'stream' */
3619                 if (avformat_find_stream_info(infile, NULL) < 0) {
3620                     http_log("Could not find codec parameters from '%s'\n",
3621                              stream->feed_filename);
3622                     avformat_close_input(&infile);
3623                     goto fail;
3624                 }
3625                 extract_mpeg4_header(infile);
3626
3627                 for(i=0;i<infile->nb_streams;i++)
3628                     add_av_stream1(stream, infile->streams[i]->codec, 1);
3629
3630                 avformat_close_input(&infile);
3631             }
3632         }
3633     }
3634 }
3635
3636 /* compute the needed AVStream for each feed */
3637 static void build_feed_streams(void)
3638 {
3639     FFStream *stream, *feed;
3640     int i;
3641
3642     /* gather all streams */
3643     for(stream = first_stream; stream != NULL; stream = stream->next) {
3644         feed = stream->feed;
3645         if (feed) {
3646             if (stream->is_feed) {
3647                 for(i=0;i<stream->nb_streams;i++)
3648                     stream->feed_streams[i] = i;
3649             } else {
3650                 /* we handle a stream coming from a feed */
3651                 for(i=0;i<stream->nb_streams;i++)
3652                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3653             }
3654         }
3655     }
3656
3657     /* create feed files if needed */
3658     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3659         int fd;
3660
3661         if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3662             /* See if it matches */
3663             AVFormatContext *s = NULL;
3664             int matches = 0;
3665
3666             if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3667                 /* Now see if it matches */
3668                 if (s->nb_streams == feed->nb_streams) {
3669                     matches = 1;
3670                     for(i=0;i<s->nb_streams;i++) {
3671                         AVStream *sf, *ss;
3672                         sf = feed->streams[i];
3673                         ss = s->streams[i];
3674
3675                         if (sf->index != ss->index ||
3676                             sf->id != ss->id) {
3677                             http_log("Index & Id do not match for stream %d (%s)\n",
3678                                    i, feed->feed_filename);
3679                             matches = 0;
3680                         } else {
3681                             AVCodecContext *ccf, *ccs;
3682
3683                             ccf = sf->codec;
3684                             ccs = ss->codec;
3685 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3686
3687                             if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3688                                 http_log("Codecs do not match for stream %d\n", i);
3689                                 matches = 0;
3690                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3691                                 http_log("Codec bitrates do not match for stream %d\n", i);
3692                                 matches = 0;
3693                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3694                                 if (CHECK_CODEC(time_base.den) ||
3695                                     CHECK_CODEC(time_base.num) ||
3696                                     CHECK_CODEC(width) ||
3697                                     CHECK_CODEC(height)) {
3698                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3699                                     matches = 0;
3700                                 }
3701                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3702                                 if (CHECK_CODEC(sample_rate) ||
3703                                     CHECK_CODEC(channels) ||
3704                                     CHECK_CODEC(frame_size)) {
3705                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3706                                     matches = 0;
3707                                 }
3708                             } else {
3709                                 http_log("Unknown codec type\n");
3710                                 matches = 0;
3711                             }
3712                         }
3713                         if (!matches)
3714                             break;
3715                     }
3716                 } else
3717                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3718                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3719
3720                 avformat_close_input(&s);
3721             } else
3722                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3723                         feed->feed_filename);
3724
3725             if (!matches) {
3726                 if (feed->readonly) {
3727                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3728                         feed->feed_filename);
3729                     exit(1);
3730                 }
3731                 unlink(feed->feed_filename);
3732             }
3733         }
3734         if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3735             AVFormatContext s1 = {0}, *s = &s1;
3736
3737             if (feed->readonly) {
3738                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3739                     feed->feed_filename);
3740                 exit(1);
3741             }
3742
3743             /* only write the header of the ffm file */
3744             if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3745                 http_log("Could not open output feed file '%s'\n",
3746                          feed->feed_filename);
3747                 exit(1);
3748             }
3749             s->oformat = feed->fmt;
3750             s->nb_streams = feed->nb_streams;
3751             s->streams = feed->streams;
3752             if (avformat_write_header(s, NULL) < 0) {
3753                 http_log("Container doesn't supports the required parameters\n");
3754                 exit(1);
3755             }
3756             /* XXX: need better api */
3757             av_freep(&s->priv_data);
3758             avio_close(s->pb);
3759         }
3760         /* get feed size and write index */
3761         fd = open(feed->feed_filename, O_RDONLY);
3762         if (fd < 0) {
3763             http_log("Could not open output feed file '%s'\n",
3764                     feed->feed_filename);
3765             exit(1);
3766         }
3767
3768         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3769         feed->feed_size = lseek(fd, 0, SEEK_END);
3770         /* ensure that we do not wrap before the end of file */
3771         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3772             feed->feed_max_size = feed->feed_size;
3773
3774         close(fd);
3775     }
3776 }
3777
3778 /* compute the bandwidth used by each stream */
3779 static void compute_bandwidth(void)
3780 {
3781     unsigned bandwidth;
3782     int i;
3783     FFStream *stream;
3784
3785     for(stream = first_stream; stream != NULL; stream = stream->next) {
3786         bandwidth = 0;
3787         for(i=0;i<stream->nb_streams;i++) {
3788             AVStream *st = stream->streams[i];
3789             switch(st->codec->codec_type) {
3790             case AVMEDIA_TYPE_AUDIO:
3791             case AVMEDIA_TYPE_VIDEO:
3792                 bandwidth += st->codec->bit_rate;
3793                 break;
3794             default:
3795                 break;
3796             }
3797         }
3798         stream->bandwidth = (bandwidth + 999) / 1000;
3799     }
3800 }
3801
3802 /* add a codec and set the default parameters */
3803 static void add_codec(FFStream *stream, AVCodecContext *av)
3804 {
3805     AVStream *st;
3806
3807     /* compute default parameters */
3808     switch(av->codec_type) {
3809     case AVMEDIA_TYPE_AUDIO:
3810         if (av->bit_rate == 0)
3811             av->bit_rate = 64000;
3812         if (av->sample_rate == 0)
3813             av->sample_rate = 22050;
3814         if (av->channels == 0)
3815             av->channels = 1;
3816         break;
3817     case AVMEDIA_TYPE_VIDEO:
3818         if (av->bit_rate == 0)
3819             av->bit_rate = 64000;
3820         if (av->time_base.num == 0){
3821             av->time_base.den = 5;
3822             av->time_base.num = 1;
3823         }
3824         if (av->width == 0 || av->height == 0) {
3825             av->width = 160;
3826             av->height = 128;
3827         }
3828         /* Bitrate tolerance is less for streaming */
3829         if (av->bit_rate_tolerance == 0)
3830             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3831                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3832         if (av->qmin == 0)
3833             av->qmin = 3;
3834         if (av->qmax == 0)
3835             av->qmax = 31;
3836         if (av->max_qdiff == 0)
3837             av->max_qdiff = 3;
3838         av->qcompress = 0.5;
3839         av->qblur = 0.5;
3840
3841         if (!av->nsse_weight)
3842             av->nsse_weight = 8;
3843
3844         av->frame_skip_cmp = FF_CMP_DCTMAX;
3845         if (!av->me_method)
3846             av->me_method = ME_EPZS;
3847         av->rc_buffer_aggressivity = 1.0;
3848
3849         if (!av->rc_eq)
3850             av->rc_eq = "tex^qComp";
3851         if (!av->i_quant_factor)
3852             av->i_quant_factor = -0.8;
3853         if (!av->b_quant_factor)
3854             av->b_quant_factor = 1.25;
3855         if (!av->b_quant_offset)
3856             av->b_quant_offset = 1.25;
3857         if (!av->rc_max_rate)
3858             av->rc_max_rate = av->bit_rate * 2;
3859
3860         if (av->rc_max_rate && !av->rc_buffer_size) {
3861             av->rc_buffer_size = av->rc_max_rate;
3862         }
3863
3864
3865         break;
3866     default:
3867         abort();
3868     }
3869
3870     st = av_mallocz(sizeof(AVStream));
3871     if (!st)
3872         return;
3873     st->codec = avcodec_alloc_context3(NULL);
3874     stream->streams[stream->nb_streams++] = st;
3875     memcpy(st->codec, av, sizeof(AVCodecContext));
3876 }
3877
3878 static enum CodecID opt_audio_codec(const char *arg)
3879 {
3880     AVCodec *p= avcodec_find_encoder_by_name(arg);
3881
3882     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3883         return CODEC_ID_NONE;
3884
3885     return p->id;
3886 }
3887
3888 static enum CodecID opt_video_codec(const char *arg)
3889 {
3890     AVCodec *p= avcodec_find_encoder_by_name(arg);
3891
3892     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3893         return CODEC_ID_NONE;
3894
3895     return p->id;
3896 }
3897
3898 /* simplistic plugin support */
3899
3900 #if HAVE_DLOPEN
3901 static void load_module(const char *filename)
3902 {
3903     void *dll;
3904     void (*init_func)(void);
3905     dll = dlopen(filename, RTLD_NOW);
3906     if (!dll) {
3907         fprintf(stderr, "Could not load module '%s' - %s\n",
3908                 filename, dlerror());
3909         return;
3910     }
3911
3912     init_func = dlsym(dll, "ffserver_module_init");
3913     if (!init_func) {
3914         fprintf(stderr,
3915                 "%s: init function 'ffserver_module_init()' not found\n",
3916                 filename);
3917         dlclose(dll);
3918     }
3919
3920     init_func();
3921 }
3922 #endif
3923
3924 static int ffserver_opt_default(const char *opt, const char *arg,
3925                        AVCodecContext *avctx, int type)
3926 {
3927     int ret = 0;
3928     const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3929     if(o)
3930         ret = av_opt_set(avctx, opt, arg, 0);
3931     return ret;
3932 }
3933
3934 static int ffserver_opt_preset(const char *arg,
3935                        AVCodecContext *avctx, int type,
3936                        enum CodecID *audio_id, enum CodecID *video_id)
3937 {
3938     FILE *f=NULL;
3939     char filename[1000], tmp[1000], tmp2[1000], line[1000];
3940     int ret = 0;
3941     AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3942
3943     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3944                               codec ? codec->name : NULL))) {
3945         fprintf(stderr, "File for preset '%s' not found\n", arg);
3946         return 1;
3947     }
3948
3949     while(!feof(f)){
3950         int e= fscanf(f, "%999[^\n]\n", line) - 1;
3951         if(line[0] == '#' && !e)
3952             continue;
3953         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3954         if(e){
3955             fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3956             ret = 1;
3957             break;
3958         }
3959         if(!strcmp(tmp, "acodec")){
3960             *audio_id = opt_audio_codec(tmp2);
3961         }else if(!strcmp(tmp, "vcodec")){
3962             *video_id = opt_video_codec(tmp2);
3963         }else if(!strcmp(tmp, "scodec")){
3964             /* opt_subtitle_codec(tmp2); */
3965         }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
3966             fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3967             ret = 1;
3968             break;
3969         }
3970     }
3971
3972     fclose(f);
3973
3974     return ret;
3975 }
3976
3977 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
3978                                              const char *mime_type)
3979 {
3980     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3981
3982     if (fmt) {
3983         AVOutputFormat *stream_fmt;
3984         char stream_format_name[64];
3985
3986         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3987         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3988
3989         if (stream_fmt)
3990             fmt = stream_fmt;
3991     }
3992
3993     return fmt;
3994 }
3995
3996 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
3997 {
3998     va_list vl;
3999     va_start(vl, fmt);
4000     fprintf(stderr, "%s:%d: ", filename, line_num);
4001     vfprintf(stderr, fmt, vl);
4002     va_end(vl);
4003
4004     (*errors)++;
4005 }
4006
4007 static int parse_ffconfig(const char *filename)
4008 {
4009     FILE *f;
4010     char line[1024];
4011     char cmd[64];
4012     char arg[1024];
4013     const char *p;
4014     int val, errors, line_num;
4015     FFStream **last_stream, *stream, *redirect;
4016     FFStream **last_feed, *feed, *s;
4017     AVCodecContext audio_enc, video_enc;
4018     enum CodecID audio_id, video_id;
4019
4020     f = fopen(filename, "r");
4021     if (!f) {
4022         perror(filename);
4023         return -1;
4024     }
4025
4026     errors = 0;
4027     line_num = 0;
4028     first_stream = NULL;
4029     last_stream = &first_stream;
4030     first_feed = NULL;
4031     last_feed = &first_feed;
4032     stream = NULL;
4033     feed = NULL;
4034     redirect = NULL;
4035     audio_id = CODEC_ID_NONE;
4036     video_id = CODEC_ID_NONE;
4037
4038 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4039     for(;;) {
4040         if (fgets(line, sizeof(line), f) == NULL)
4041             break;
4042         line_num++;
4043         p = line;
4044         while (isspace(*p))
4045             p++;
4046         if (*p == '\0' || *p == '#')
4047             continue;
4048
4049         get_arg(cmd, sizeof(cmd), &p);
4050
4051         if (!av_strcasecmp(cmd, "Port")) {
4052             get_arg(arg, sizeof(arg), &p);
4053             val = atoi(arg);
4054             if (val < 1 || val > 65536) {
4055                 ERROR("Invalid_port: %s\n", arg);
4056             }
4057             my_http_addr.sin_port = htons(val);
4058         } else if (!av_strcasecmp(cmd, "BindAddress")) {
4059             get_arg(arg, sizeof(arg), &p);
4060             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4061                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4062             }
4063         } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4064             ffserver_daemon = 0;
4065         } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4066             get_arg(arg, sizeof(arg), &p);
4067             val = atoi(arg);
4068             if (val < 1 || val > 65536) {
4069                 ERROR("%s:%d: Invalid port: %s\n", arg);
4070             }
4071             my_rtsp_addr.sin_port = htons(atoi(arg));
4072         } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4073             get_arg(arg, sizeof(arg), &p);
4074             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4075                 ERROR("Invalid host/IP address: %s\n", arg);
4076             }
4077         } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4078             get_arg(arg, sizeof(arg), &p);
4079             val = atoi(arg);
4080             if (val < 1 || val > 65536) {
4081                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4082             }
4083             nb_max_http_connections = val;
4084         } else if (!av_strcasecmp(cmd, "MaxClients")) {
4085             get_arg(arg, sizeof(arg), &p);
4086             val = atoi(arg);
4087             if (val < 1 || val > nb_max_http_connections) {
4088                 ERROR("Invalid MaxClients: %s\n", arg);
4089             } else {
4090                 nb_max_connections = val;
4091             }
4092         } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4093             int64_t llval;
4094             get_arg(arg, sizeof(arg), &p);
4095             llval = atoll(arg);
4096             if (llval < 10 || llval > 10000000) {
4097                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4098             } else
4099                 max_bandwidth = llval;
4100         } else if (!av_strcasecmp(cmd, "CustomLog")) {
4101             if (!ffserver_debug)
4102                 get_arg(logfilename, sizeof(logfilename), &p);
4103         } else if (!av_strcasecmp(cmd, "<Feed")) {
4104             /*********************************************/
4105             /* Feed related options */
4106             char *q;
4107             if (stream || feed) {
4108                 ERROR("Already in a tag\n");
4109             } else {
4110                 feed = av_mallocz(sizeof(FFStream));
4111                 get_arg(feed->filename, sizeof(feed->filename), &p);
4112                 q = strrchr(feed->filename, '>');
4113                 if (*q)
4114                     *q = '\0';
4115
4116                 for (s = first_feed; s; s = s->next) {
4117                     if (!strcmp(feed->filename, s->filename)) {
4118                         ERROR("Feed '%s' already registered\n", s->filename);
4119                     }
4120                 }
4121
4122                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4123                 /* defaut feed file */
4124                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4125                          "/tmp/%s.ffm", feed->filename);
4126                 feed->feed_max_size = 5 * 1024 * 1024;
4127                 feed->is_feed = 1;
4128                 feed->feed = feed; /* self feeding :-) */
4129
4130                 /* add in stream list */
4131                 *last_stream = feed;
4132                 last_stream = &feed->next;
4133                 /* add in feed list */
4134                 *last_feed = feed;
4135                 last_feed = &feed->next_feed;
4136             }
4137         } else if (!av_strcasecmp(cmd, "Launch")) {
4138             if (feed) {
4139                 int i;
4140
4141                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4142
4143                 for (i = 0; i < 62; i++) {
4144                     get_arg(arg, sizeof(arg), &p);
4145                     if (!arg[0])
4146                         break;
4147
4148                     feed->child_argv[i] = av_strdup(arg);
4149                 }
4150
4151                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4152
4153                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4154                     "http://%s:%d/%s",
4155                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4156                     inet_ntoa(my_http_addr.sin_addr),
4157                     ntohs(my_http_addr.sin_port), feed->filename);
4158             }
4159         } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4160             if (feed) {
4161                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4162                 feed->readonly = 1;
4163             } else if (stream) {
4164                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4165             }
4166         } else if (!av_strcasecmp(cmd, "File")) {
4167             if (feed) {
4168                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4169             } else if (stream)
4170                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4171         } else if (!av_strcasecmp(cmd, "Truncate")) {
4172             if (feed) {
4173                 get_arg(arg, sizeof(arg), &p);
4174                 feed->truncate = strtod(arg, NULL);
4175             }
4176         } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4177             if (feed) {
4178                 char *p1;
4179                 double fsize;
4180
4181                 get_arg(arg, sizeof(arg), &p);
4182                 p1 = arg;
4183                 fsize = strtod(p1, &p1);
4184                 switch(toupper(*p1)) {
4185                 case 'K':
4186                     fsize *= 1024;
4187                     break;
4188                 case 'M':
4189                     fsize *= 1024 * 1024;
4190                     break;
4191                 case 'G':
4192                     fsize *= 1024 * 1024 * 1024;
4193                     break;
4194                 }
4195                 feed->feed_max_size = (int64_t)fsize;
4196                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4197                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4198                 }
4199             }
4200         } else if (!av_strcasecmp(cmd, "</Feed>")) {
4201             if (!feed) {
4202                 ERROR("No corresponding <Feed> for </Feed>\n");
4203             }
4204             feed = NULL;
4205         } else if (!av_strcasecmp(cmd, "<Stream")) {
4206             /*********************************************/
4207             /* Stream related options */
4208             char *q;
4209             if (stream || feed) {
4210                 ERROR("Already in a tag\n");
4211             } else {
4212                 FFStream *s;
4213                 stream = av_mallocz(sizeof(FFStream));
4214                 get_arg(stream->filename, sizeof(stream->filename), &p);
4215                 q = strrchr(stream->filename, '>');
4216                 if (*q)
4217                     *q = '\0';
4218
4219                 for (s = first_stream; s; s = s->next) {
4220                     if (!strcmp(stream->filename, s->filename)) {
4221                         ERROR("Stream '%s' already registered\n", s->filename);
4222                     }
4223                 }
4224
4225                 stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4226                 avcodec_get_context_defaults3(&video_enc, NULL);
4227                 avcodec_get_context_defaults3(&audio_enc, NULL);
4228
4229                 audio_id = CODEC_ID_NONE;
4230                 video_id = CODEC_ID_NONE;
4231                 if (stream->fmt) {
4232                     audio_id = stream->fmt->audio_codec;
4233                     video_id = stream->fmt->video_codec;
4234                 }
4235
4236                 *last_stream = stream;
4237                 last_stream = &stream->next;
4238             }
4239         } else if (!av_strcasecmp(cmd, "Feed")) {
4240             get_arg(arg, sizeof(arg), &p);
4241             if (stream) {
4242                 FFStream *sfeed;
4243
4244                 sfeed = first_feed;
4245                 while (sfeed != NULL) {
4246                     if (!strcmp(sfeed->filename, arg))
4247                         break;
4248                     sfeed = sfeed->next_feed;
4249                 }
4250                 if (!sfeed)
4251                     ERROR("feed '%s' not defined\n", arg);
4252                 else
4253                     stream->feed = sfeed;
4254             }
4255         } else if (!av_strcasecmp(cmd, "Format")) {
4256             get_arg(arg, sizeof(arg), &p);
4257             if (stream) {
4258                 if (!strcmp(arg, "status")) {
4259                     stream->stream_type = STREAM_TYPE_STATUS;
4260                     stream->fmt = NULL;
4261                 } else {
4262                     stream->stream_type = STREAM_TYPE_LIVE;
4263                     /* jpeg cannot be used here, so use single frame jpeg */
4264                     if (!strcmp(arg, "jpeg"))
4265                         strcpy(arg, "mjpeg");
4266                     stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4267                     if (!stream->fmt) {
4268                         ERROR("Unknown Format: %s\n", arg);
4269                     }
4270                 }
4271                 if (stream->fmt) {
4272                     audio_id = stream->fmt->audio_codec;
4273                     video_id = stream->fmt->video_codec;
4274                 }
4275             }
4276         } else if (!av_strcasecmp(cmd, "InputFormat")) {
4277             get_arg(arg, sizeof(arg), &p);
4278             if (stream) {
4279                 stream->ifmt = av_find_input_format(arg);
4280                 if (!stream->ifmt) {
4281                     ERROR("Unknown input format: %s\n", arg);
4282                 }
4283             }
4284         } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4285             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4286                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4287             } else {
4288                 ERROR("FaviconURL only permitted for status streams\n");
4289             }
4290         } else if (!av_strcasecmp(cmd, "Author")) {
4291             if (stream)
4292                 get_arg(stream->author, sizeof(stream->author), &p);
4293         } else if (!av_strcasecmp(cmd, "Comment")) {
4294             if (stream)
4295                 get_arg(stream->comment, sizeof(stream->comment), &p);
4296         } else if (!av_strcasecmp(cmd, "Copyright")) {
4297             if (stream)
4298                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4299         } else if (!av_strcasecmp(cmd, "Title")) {
4300             if (stream)
4301                 get_arg(stream->title, sizeof(stream->title), &p);
4302         } else if (!av_strcasecmp(cmd, "Preroll")) {
4303             get_arg(arg, sizeof(arg), &p);
4304             if (stream)
4305                 stream->prebuffer = atof(arg) * 1000;
4306         } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4307             if (stream)
4308                 stream->send_on_key = 1;
4309         } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4310             get_arg(arg, sizeof(arg), &p);
4311             audio_id = opt_audio_codec(arg);
4312             if (audio_id == CODEC_ID_NONE) {
4313                 ERROR("Unknown AudioCodec: %s\n", arg);
4314             }
4315         } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4316             get_arg(arg, sizeof(arg), &p);
4317             video_id = opt_video_codec(arg);
4318             if (video_id == CODEC_ID_NONE) {
4319                 ERROR("Unknown VideoCodec: %s\n", arg);
4320             }
4321         } else if (!av_strcasecmp(cmd, "MaxTime")) {
4322             get_arg(arg, sizeof(arg), &p);
4323             if (stream)
4324                 stream->max_time = atof(arg) * 1000;
4325         } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4326             get_arg(arg, sizeof(arg), &p);
4327             if (stream)
4328                 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4329         } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4330             get_arg(arg, sizeof(arg), &p);
4331             if (stream)
4332                 audio_enc.channels = atoi(arg);
4333         } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4334             get_arg(arg, sizeof(arg), &p);
4335             if (stream)
4336                 audio_enc.sample_rate = atoi(arg);
4337         } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4338             get_arg(arg, sizeof(arg), &p);
4339             if (stream) {
4340 //                audio_enc.quality = atof(arg) * 1000;
4341             }
4342         } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4343             if (stream) {
4344                 int minrate, maxrate;
4345
4346                 get_arg(arg, sizeof(arg), &p);
4347
4348                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4349                     video_enc.rc_min_rate = minrate * 1000;
4350                     video_enc.rc_max_rate = maxrate * 1000;
4351                 } else {
4352                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4353                 }
4354             }
4355         } else if (!av_strcasecmp(cmd, "Debug")) {
4356             if (stream) {
4357                 get_arg(arg, sizeof(arg), &p);
4358                 video_enc.debug = strtol(arg,0,0);
4359             }
4360         } else if (!av_strcasecmp(cmd, "Strict")) {
4361             if (stream) {
4362                 get_arg(arg, sizeof(arg), &p);
4363                 video_enc.strict_std_compliance = atoi(arg);
4364             }
4365         } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4366             if (stream) {
4367                 get_arg(arg, sizeof(arg), &p);
4368                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4369             }
4370         } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4371             if (stream) {
4372                 get_arg(arg, sizeof(arg), &p);
4373                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4374             }
4375         } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4376             get_arg(arg, sizeof(arg), &p);
4377             if (stream) {
4378                 video_enc.bit_rate = atoi(arg) * 1000;
4379             }
4380         } else if (!av_strcasecmp(cmd, "VideoSize")) {
4381             get_arg(arg, sizeof(arg), &p);
4382             if (stream) {
4383                 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4384                 if ((video_enc.width % 16) != 0 ||
4385                     (video_enc.height % 16) != 0) {
4386                     ERROR("Image size must be a multiple of 16\n");
4387                 }
4388             }
4389         } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4390             get_arg(arg, sizeof(arg), &p);
4391             if (stream) {
4392                 AVRational frame_rate;
4393                 if (av_parse_video_rate(&frame_rate, arg) < 0) {
4394                     ERROR("Incorrect frame rate: %s\n", arg);
4395                 } else {
4396                     video_enc.time_base.num = frame_rate.den;
4397                     video_enc.time_base.den = frame_rate.num;
4398                 }
4399             }
4400         } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4401             get_arg(arg, sizeof(arg), &p);
4402             if (stream)
4403                 video_enc.gop_size = atoi(arg);
4404         } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4405             if (stream)
4406                 video_enc.gop_size = 1;
4407         } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4408             if (stream)
4409                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4410         } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4411             if (stream) {
4412                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4413                 video_enc.flags |= CODEC_FLAG_4MV;
4414             }
4415         } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4416                    !av_strcasecmp(cmd, "AVOptionAudio")) {
4417             char arg2[1024];
4418             AVCodecContext *avctx;
4419             int type;
4420             get_arg(arg, sizeof(arg), &p);
4421             get_arg(arg2, sizeof(arg2), &p);
4422             if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4423                 avctx = &video_enc;
4424                 type = AV_OPT_FLAG_VIDEO_PARAM;
4425             } else {
4426                 avctx = &audio_enc;
4427                 type = AV_OPT_FLAG_AUDIO_PARAM;
4428             }
4429             if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4430                 ERROR("AVOption error: %s %s\n", arg, arg2);
4431             }
4432         } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4433                    !av_strcasecmp(cmd, "AVPresetAudio")) {
4434             AVCodecContext *avctx;
4435             int type;
4436             get_arg(arg, sizeof(arg), &p);
4437             if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4438                 avctx = &video_enc;
4439                 video_enc.codec_id = video_id;
4440                 type = AV_OPT_FLAG_VIDEO_PARAM;
4441             } else {
4442                 avctx = &audio_enc;
4443                 audio_enc.codec_id = audio_id;
4444                 type = AV_OPT_FLAG_AUDIO_PARAM;
4445             }
4446             if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4447                 ERROR("AVPreset error: %s\n", arg);
4448             }
4449         } else if (!av_strcasecmp(cmd, "VideoTag")) {
4450             get_arg(arg, sizeof(arg), &p);
4451             if ((strlen(arg) == 4) && stream)
4452                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4453         } else if (!av_strcasecmp(cmd, "BitExact")) {
4454             if (stream)
4455                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4456         } else if (!av_strcasecmp(cmd, "DctFastint")) {
4457             if (stream)
4458                 video_enc.dct_algo  = FF_DCT_FASTINT;
4459         } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4460             if (stream)
4461                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4462         } else if (!av_strcasecmp(cmd, "Qscale")) {
4463             get_arg(arg, sizeof(arg), &p);
4464             if (stream) {
4465                 video_enc.flags |= CODEC_FLAG_QSCALE;
4466                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4467             }
4468         } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4469             get_arg(arg, sizeof(arg), &p);
4470             if (stream) {
4471                 video_enc.max_qdiff = atoi(arg);
4472                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4473                     ERROR("VideoQDiff out of range\n");
4474                 }
4475             }
4476         } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4477             get_arg(arg, sizeof(arg), &p);
4478             if (stream) {
4479                 video_enc.qmax = atoi(arg);
4480                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4481                     ERROR("VideoQMax out of range\n");
4482                 }
4483             }
4484         } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4485             get_arg(arg, sizeof(arg), &p);
4486             if (stream) {
4487                 video_enc.qmin = atoi(arg);
4488                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4489                     ERROR("VideoQMin out of range\n");
4490                 }
4491             }
4492         } else if (!av_strcasecmp(cmd, "LumaElim")) {
4493             get_arg(arg, sizeof(arg), &p);
4494             if (stream)
4495                 video_enc.luma_elim_threshold = atoi(arg);
4496         } else if (!av_strcasecmp(cmd, "ChromaElim")) {
4497             get_arg(arg, sizeof(arg), &p);
4498             if (stream)
4499                 video_enc.chroma_elim_threshold = atoi(arg);
4500         } else if (!av_strcasecmp(cmd, "LumiMask")) {
4501             get_arg(arg, sizeof(arg), &p);
4502             if (stream)
4503                 video_enc.lumi_masking = atof(arg);
4504         } else if (!av_strcasecmp(cmd, "DarkMask")) {
4505             get_arg(arg, sizeof(arg), &p);
4506             if (stream)
4507                 video_enc.dark_masking = atof(arg);
4508         } else if (!av_strcasecmp(cmd, "NoVideo")) {
4509             video_id = CODEC_ID_NONE;
4510         } else if (!av_strcasecmp(cmd, "NoAudio")) {
4511             audio_id = CODEC_ID_NONE;
4512         } else if (!av_strcasecmp(cmd, "ACL")) {
4513             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4514         } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4515             if (stream) {
4516                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4517             }
4518         } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4519             get_arg(arg, sizeof(arg), &p);
4520             if (stream) {
4521                 av_freep(&stream->rtsp_option);
4522                 stream->rtsp_option = av_strdup(arg);
4523             }
4524         } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4525             get_arg(arg, sizeof(arg), &p);
4526             if (stream) {
4527                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4528                     ERROR("Invalid host/IP address: %s\n", arg);
4529                 }
4530                 stream->is_multicast = 1;
4531                 stream->loop = 1; /* default is looping */
4532             }
4533         } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4534             get_arg(arg, sizeof(arg), &p);
4535             if (stream)
4536                 stream->multicast_port = atoi(arg);
4537         } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4538             get_arg(arg, sizeof(arg), &p);
4539             if (stream)
4540                 stream->multicast_ttl = atoi(arg);
4541         } else if (!av_strcasecmp(cmd, "NoLoop")) {
4542             if (stream)
4543                 stream->loop = 0;
4544         } else if (!av_strcasecmp(cmd, "</Stream>")) {
4545             if (!stream) {
4546                 ERROR("No corresponding <Stream> for </Stream>\n");
4547             } else {
4548                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4549                     if (audio_id != CODEC_ID_NONE) {
4550                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4551                         audio_enc.codec_id = audio_id;
4552                         add_codec(stream, &audio_enc);
4553                     }
4554                     if (video_id != CODEC_ID_NONE) {
4555                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4556                         video_enc.codec_id = video_id;
4557                         add_codec(stream, &video_enc);
4558                     }
4559                 }
4560                 stream = NULL;
4561             }
4562         } else if (!av_strcasecmp(cmd, "<Redirect")) {
4563             /*********************************************/
4564             char *q;
4565             if (stream || feed || redirect) {
4566                 ERROR("Already in a tag\n");
4567             } else {
4568                 redirect = av_mallocz(sizeof(FFStream));
4569                 *last_stream = redirect;
4570                 last_stream = &redirect->next;
4571
4572                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4573                 q = strrchr(redirect->filename, '>');
4574                 if (*q)
4575                     *q = '\0';
4576                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4577             }
4578         } else if (!av_strcasecmp(cmd, "URL")) {
4579             if (redirect)
4580                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4581         } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4582             if (!redirect) {
4583                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4584             } else {
4585                 if (!redirect->feed_filename[0]) {
4586                     ERROR("No URL found for <Redirect>\n");
4587                 }
4588                 redirect = NULL;
4589             }
4590         } else if (!av_strcasecmp(cmd, "LoadModule")) {
4591             get_arg(arg, sizeof(arg), &p);
4592 #if HAVE_DLOPEN
4593             load_module(arg);
4594 #else
4595             ERROR("Module support not compiled into this version: '%s'\n", arg);
4596 #endif
4597         } else {
4598             ERROR("Incorrect keyword: '%s'\n", cmd);
4599         }
4600     }
4601 #undef ERROR
4602
4603     fclose(f);
4604     if (errors)
4605         return -1;
4606     else
4607         return 0;
4608 }
4609
4610 static void handle_child_exit(int sig)
4611 {
4612     pid_t pid;
4613     int status;
4614
4615     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4616         FFStream *feed;
4617
4618         for (feed = first_feed; feed; feed = feed->next) {
4619             if (feed->pid == pid) {
4620                 int uptime = time(0) - feed->pid_start;
4621
4622                 feed->pid = 0;
4623                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4624
4625                 if (uptime < 30)
4626                     /* Turn off any more restarts */
4627                     feed->child_argv = 0;
4628             }
4629         }
4630     }
4631
4632     need_to_start_children = 1;
4633 }
4634
4635 static void opt_debug(void)
4636 {
4637     ffserver_debug = 1;
4638     ffserver_daemon = 0;
4639     logfilename[0] = '-';
4640 }
4641
4642 static int opt_help(const char *opt, const char *arg)
4643 {
4644     printf("usage: ffserver [options]\n"
4645            "Hyper fast multi format Audio/Video streaming server\n");
4646     printf("\n");
4647     show_help_options(options, "Main options:\n", 0, 0);
4648     return 0;
4649 }
4650
4651 static const OptionDef options[] = {
4652 #include "cmdutils_common_opts.h"
4653     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4654     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4655     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4656     { NULL },
4657 };
4658
4659 int main(int argc, char **argv)
4660 {
4661     struct sigaction sigact;
4662
4663     parse_loglevel(argc, argv, options);
4664     av_register_all();
4665     avformat_network_init();
4666
4667     show_banner(argc, argv, options);
4668
4669     my_program_name = argv[0];
4670     my_program_dir = getcwd(0, 0);
4671     ffserver_daemon = 1;
4672
4673     parse_options(NULL, argc, argv, options, NULL);
4674
4675     unsetenv("http_proxy");             /* Kill the http_proxy */
4676
4677     av_lfg_init(&random_state, av_get_random_seed());
4678
4679     memset(&sigact, 0, sizeof(sigact));
4680     sigact.sa_handler = handle_child_exit;
4681     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4682     sigaction(SIGCHLD, &sigact, 0);
4683
4684     if (parse_ffconfig(config_filename) < 0) {
4685         fprintf(stderr, "Incorrect config file - exiting.\n");
4686         exit(1);
4687     }
4688
4689     /* open log file if needed */
4690     if (logfilename[0] != '\0') {
4691         if (!strcmp(logfilename, "-"))
4692             logfile = stdout;
4693         else
4694             logfile = fopen(logfilename, "a");
4695         av_log_set_callback(http_av_log);
4696     }
4697
4698     build_file_streams();
4699
4700     build_feed_streams();
4701
4702     compute_bandwidth();
4703
4704     /* put the process in background and detach it from its TTY */
4705     if (ffserver_daemon) {
4706         int pid;
4707
4708         pid = fork();
4709         if (pid < 0) {
4710             perror("fork");
4711             exit(1);
4712         } else if (pid > 0) {
4713             /* parent : exit */
4714             exit(0);
4715         } else {
4716             /* child */
4717             setsid();
4718             close(0);
4719             open("/dev/null", O_RDWR);
4720             if (strcmp(logfilename, "-") != 0) {
4721                 close(1);
4722                 dup(0);
4723             }
4724             close(2);
4725             dup(0);
4726         }
4727     }
4728
4729     /* signal init */
4730     signal(SIGPIPE, SIG_IGN);
4731
4732     if (ffserver_daemon)
4733         chdir("/");
4734
4735     if (http_server() < 0) {
4736         http_log("Could not start server\n");
4737         exit(1);
4738     }
4739
4740     return 0;
4741 }