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