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