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