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