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