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