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