]> git.sesse.net Git - ffmpeg/blob - ffserver.c
Merge remote-tracking branch 'qatar/master'
[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 = av_mallocz(sizeof(*ctx->streams) * ctx->nb_streams);
3390     if (!ctx->streams)
3391         goto fail;
3392     ctx->streams[0] = st;
3393
3394     if (!c->stream->feed ||
3395         c->stream->feed == c->stream)
3396         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3397     else
3398         memcpy(st,
3399                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3400                sizeof(AVStream));
3401     st->priv_data = NULL;
3402
3403     /* build destination RTP address */
3404     ipaddr = inet_ntoa(dest_addr->sin_addr);
3405
3406     switch(c->rtp_protocol) {
3407     case RTSP_LOWER_TRANSPORT_UDP:
3408     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3409         /* RTP/UDP case */
3410
3411         /* XXX: also pass as parameter to function ? */
3412         if (c->stream->is_multicast) {
3413             int ttl;
3414             ttl = c->stream->multicast_ttl;
3415             if (!ttl)
3416                 ttl = 16;
3417             snprintf(ctx->filename, sizeof(ctx->filename),
3418                      "rtp://%s:%d?multicast=1&ttl=%d",
3419                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3420         } else {
3421             snprintf(ctx->filename, sizeof(ctx->filename),
3422                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3423         }
3424
3425         if (url_open(&h, ctx->filename, AVIO_FLAG_WRITE) < 0)
3426             goto fail;
3427         c->rtp_handles[stream_index] = h;
3428         max_packet_size = url_get_max_packet_size(h);
3429         break;
3430     case RTSP_LOWER_TRANSPORT_TCP:
3431         /* RTP/TCP case */
3432         c->rtsp_c = rtsp_c;
3433         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3434         break;
3435     default:
3436         goto fail;
3437     }
3438
3439     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3440              ipaddr, ntohs(dest_addr->sin_port),
3441              c->stream->filename, stream_index, c->protocol);
3442
3443     /* normally, no packets should be output here, but the packet size may be checked */
3444     if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3445         /* XXX: close stream */
3446         goto fail;
3447     }
3448     av_set_parameters(ctx, NULL);
3449     if (av_write_header(ctx) < 0) {
3450     fail:
3451         if (h)
3452             url_close(h);
3453         av_free(ctx);
3454         return -1;
3455     }
3456     avio_close_dyn_buf(ctx->pb, &dummy_buf);
3457     av_free(dummy_buf);
3458
3459     c->rtp_ctx[stream_index] = ctx;
3460     return 0;
3461 }
3462
3463 /********************************************************************/
3464 /* ffserver initialization */
3465
3466 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3467 {
3468     AVStream *fst;
3469
3470     fst = av_mallocz(sizeof(AVStream));
3471     if (!fst)
3472         return NULL;
3473     if (copy) {
3474         fst->codec= avcodec_alloc_context();
3475         memcpy(fst->codec, codec, sizeof(AVCodecContext));
3476         if (codec->extradata_size) {
3477             fst->codec->extradata = av_malloc(codec->extradata_size);
3478             memcpy(fst->codec->extradata, codec->extradata,
3479                 codec->extradata_size);
3480         }
3481     } else {
3482         /* live streams must use the actual feed's codec since it may be
3483          * updated later to carry extradata needed by the streams.
3484          */
3485         fst->codec = codec;
3486     }
3487     fst->priv_data = av_mallocz(sizeof(FeedData));
3488     fst->index = stream->nb_streams;
3489     av_set_pts_info(fst, 33, 1, 90000);
3490     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3491     stream->streams[stream->nb_streams++] = fst;
3492     return fst;
3493 }
3494
3495 /* return the stream number in the feed */
3496 static int add_av_stream(FFStream *feed, AVStream *st)
3497 {
3498     AVStream *fst;
3499     AVCodecContext *av, *av1;
3500     int i;
3501
3502     av = st->codec;
3503     for(i=0;i<feed->nb_streams;i++) {
3504         st = feed->streams[i];
3505         av1 = st->codec;
3506         if (av1->codec_id == av->codec_id &&
3507             av1->codec_type == av->codec_type &&
3508             av1->bit_rate == av->bit_rate) {
3509
3510             switch(av->codec_type) {
3511             case AVMEDIA_TYPE_AUDIO:
3512                 if (av1->channels == av->channels &&
3513                     av1->sample_rate == av->sample_rate)
3514                     goto found;
3515                 break;
3516             case AVMEDIA_TYPE_VIDEO:
3517                 if (av1->width == av->width &&
3518                     av1->height == av->height &&
3519                     av1->time_base.den == av->time_base.den &&
3520                     av1->time_base.num == av->time_base.num &&
3521                     av1->gop_size == av->gop_size)
3522                     goto found;
3523                 break;
3524             default:
3525                 abort();
3526             }
3527         }
3528     }
3529
3530     fst = add_av_stream1(feed, av, 0);
3531     if (!fst)
3532         return -1;
3533     return feed->nb_streams - 1;
3534  found:
3535     return i;
3536 }
3537
3538 static void remove_stream(FFStream *stream)
3539 {
3540     FFStream **ps;
3541     ps = &first_stream;
3542     while (*ps != NULL) {
3543         if (*ps == stream)
3544             *ps = (*ps)->next;
3545         else
3546             ps = &(*ps)->next;
3547     }
3548 }
3549
3550 /* specific mpeg4 handling : we extract the raw parameters */
3551 static void extract_mpeg4_header(AVFormatContext *infile)
3552 {
3553     int mpeg4_count, i, size;
3554     AVPacket pkt;
3555     AVStream *st;
3556     const uint8_t *p;
3557
3558     mpeg4_count = 0;
3559     for(i=0;i<infile->nb_streams;i++) {
3560         st = infile->streams[i];
3561         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3562             st->codec->extradata_size == 0) {
3563             mpeg4_count++;
3564         }
3565     }
3566     if (!mpeg4_count)
3567         return;
3568
3569     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3570     while (mpeg4_count > 0) {
3571         if (av_read_packet(infile, &pkt) < 0)
3572             break;
3573         st = infile->streams[pkt.stream_index];
3574         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3575             st->codec->extradata_size == 0) {
3576             av_freep(&st->codec->extradata);
3577             /* fill extradata with the header */
3578             /* XXX: we make hard suppositions here ! */
3579             p = pkt.data;
3580             while (p < pkt.data + pkt.size - 4) {
3581                 /* stop when vop header is found */
3582                 if (p[0] == 0x00 && p[1] == 0x00 &&
3583                     p[2] == 0x01 && p[3] == 0xb6) {
3584                     size = p - pkt.data;
3585                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3586                     st->codec->extradata = av_malloc(size);
3587                     st->codec->extradata_size = size;
3588                     memcpy(st->codec->extradata, pkt.data, size);
3589                     break;
3590                 }
3591                 p++;
3592             }
3593             mpeg4_count--;
3594         }
3595         av_free_packet(&pkt);
3596     }
3597 }
3598
3599 /* compute the needed AVStream for each file */
3600 static void build_file_streams(void)
3601 {
3602     FFStream *stream, *stream_next;
3603     AVFormatContext *infile;
3604     int i, ret;
3605
3606     /* gather all streams */
3607     for(stream = first_stream; stream != NULL; stream = stream_next) {
3608         stream_next = stream->next;
3609         if (stream->stream_type == STREAM_TYPE_LIVE &&
3610             !stream->feed) {
3611             /* the stream comes from a file */
3612             /* try to open the file */
3613             /* open stream */
3614             stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
3615             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3616                 /* specific case : if transport stream output to RTP,
3617                    we use a raw transport stream reader */
3618                 stream->ap_in->mpeg2ts_raw = 1;
3619                 stream->ap_in->mpeg2ts_compute_pcr = 1;
3620             }
3621
3622             http_log("Opening file '%s'\n", stream->feed_filename);
3623             if ((ret = av_open_input_file(&infile, stream->feed_filename,
3624                                           stream->ifmt, 0, stream->ap_in)) < 0) {
3625                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3626                 /* remove stream (no need to spend more time on it) */
3627             fail:
3628                 remove_stream(stream);
3629             } else {
3630                 /* find all the AVStreams inside and reference them in
3631                    'stream' */
3632                 if (av_find_stream_info(infile) < 0) {
3633                     http_log("Could not find codec parameters from '%s'\n",
3634                              stream->feed_filename);
3635                     av_close_input_file(infile);
3636                     goto fail;
3637                 }
3638                 extract_mpeg4_header(infile);
3639
3640                 for(i=0;i<infile->nb_streams;i++)
3641                     add_av_stream1(stream, infile->streams[i]->codec, 1);
3642
3643                 av_close_input_file(infile);
3644             }
3645         }
3646     }
3647 }
3648
3649 /* compute the needed AVStream for each feed */
3650 static void build_feed_streams(void)
3651 {
3652     FFStream *stream, *feed;
3653     int i;
3654
3655     /* gather all streams */
3656     for(stream = first_stream; stream != NULL; stream = stream->next) {
3657         feed = stream->feed;
3658         if (feed) {
3659             if (!stream->is_feed) {
3660                 /* we handle a stream coming from a feed */
3661                 for(i=0;i<stream->nb_streams;i++)
3662                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3663             }
3664         }
3665     }
3666
3667     /* gather all streams */
3668     for(stream = first_stream; stream != NULL; stream = stream->next) {
3669         feed = stream->feed;
3670         if (feed) {
3671             if (stream->is_feed) {
3672                 for(i=0;i<stream->nb_streams;i++)
3673                     stream->feed_streams[i] = i;
3674             }
3675         }
3676     }
3677
3678     /* create feed files if needed */
3679     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3680         int fd;
3681
3682         if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3683             /* See if it matches */
3684             AVFormatContext *s;
3685             int matches = 0;
3686
3687             if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
3688                 /* Now see if it matches */
3689                 if (s->nb_streams == feed->nb_streams) {
3690                     matches = 1;
3691                     for(i=0;i<s->nb_streams;i++) {
3692                         AVStream *sf, *ss;
3693                         sf = feed->streams[i];
3694                         ss = s->streams[i];
3695
3696                         if (sf->index != ss->index ||
3697                             sf->id != ss->id) {
3698                             http_log("Index & Id do not match for stream %d (%s)\n",
3699                                    i, feed->feed_filename);
3700                             matches = 0;
3701                         } else {
3702                             AVCodecContext *ccf, *ccs;
3703
3704                             ccf = sf->codec;
3705                             ccs = ss->codec;
3706 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3707
3708                             if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3709                                 http_log("Codecs do not match for stream %d\n", i);
3710                                 matches = 0;
3711                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3712                                 http_log("Codec bitrates do not match for stream %d\n", i);
3713                                 matches = 0;
3714                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3715                                 if (CHECK_CODEC(time_base.den) ||
3716                                     CHECK_CODEC(time_base.num) ||
3717                                     CHECK_CODEC(width) ||
3718                                     CHECK_CODEC(height)) {
3719                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3720                                     matches = 0;
3721                                 }
3722                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3723                                 if (CHECK_CODEC(sample_rate) ||
3724                                     CHECK_CODEC(channels) ||
3725                                     CHECK_CODEC(frame_size)) {
3726                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3727                                     matches = 0;
3728                                 }
3729                             } else {
3730                                 http_log("Unknown codec type\n");
3731                                 matches = 0;
3732                             }
3733                         }
3734                         if (!matches)
3735                             break;
3736                     }
3737                 } else
3738                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3739                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3740
3741                 av_close_input_file(s);
3742             } else
3743                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3744                         feed->feed_filename);
3745
3746             if (!matches) {
3747                 if (feed->readonly) {
3748                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3749                         feed->feed_filename);
3750                     exit(1);
3751                 }
3752                 unlink(feed->feed_filename);
3753             }
3754         }
3755         if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3756             AVFormatContext s1 = {0}, *s = &s1;
3757
3758             if (feed->readonly) {
3759                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3760                     feed->feed_filename);
3761                 exit(1);
3762             }
3763
3764             /* only write the header of the ffm file */
3765             if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3766                 http_log("Could not open output feed file '%s'\n",
3767                          feed->feed_filename);
3768                 exit(1);
3769             }
3770             s->oformat = feed->fmt;
3771             s->nb_streams = feed->nb_streams;
3772             s->streams = feed->streams;
3773             av_set_parameters(s, NULL);
3774             if (av_write_header(s) < 0) {
3775                 http_log("Container doesn't supports the required parameters\n");
3776                 exit(1);
3777             }
3778             /* XXX: need better api */
3779             av_freep(&s->priv_data);
3780             avio_close(s->pb);
3781         }
3782         /* get feed size and write index */
3783         fd = open(feed->feed_filename, O_RDONLY);
3784         if (fd < 0) {
3785             http_log("Could not open output feed file '%s'\n",
3786                     feed->feed_filename);
3787             exit(1);
3788         }
3789
3790         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3791         feed->feed_size = lseek(fd, 0, SEEK_END);
3792         /* ensure that we do not wrap before the end of file */
3793         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3794             feed->feed_max_size = feed->feed_size;
3795
3796         close(fd);
3797     }
3798 }
3799
3800 /* compute the bandwidth used by each stream */
3801 static void compute_bandwidth(void)
3802 {
3803     unsigned bandwidth;
3804     int i;
3805     FFStream *stream;
3806
3807     for(stream = first_stream; stream != NULL; stream = stream->next) {
3808         bandwidth = 0;
3809         for(i=0;i<stream->nb_streams;i++) {
3810             AVStream *st = stream->streams[i];
3811             switch(st->codec->codec_type) {
3812             case AVMEDIA_TYPE_AUDIO:
3813             case AVMEDIA_TYPE_VIDEO:
3814                 bandwidth += st->codec->bit_rate;
3815                 break;
3816             default:
3817                 break;
3818             }
3819         }
3820         stream->bandwidth = (bandwidth + 999) / 1000;
3821     }
3822 }
3823
3824 /* add a codec and set the default parameters */
3825 static void add_codec(FFStream *stream, AVCodecContext *av)
3826 {
3827     AVStream *st;
3828
3829     /* compute default parameters */
3830     switch(av->codec_type) {
3831     case AVMEDIA_TYPE_AUDIO:
3832         if (av->bit_rate == 0)
3833             av->bit_rate = 64000;
3834         if (av->sample_rate == 0)
3835             av->sample_rate = 22050;
3836         if (av->channels == 0)
3837             av->channels = 1;
3838         break;
3839     case AVMEDIA_TYPE_VIDEO:
3840         if (av->bit_rate == 0)
3841             av->bit_rate = 64000;
3842         if (av->time_base.num == 0){
3843             av->time_base.den = 5;
3844             av->time_base.num = 1;
3845         }
3846         if (av->width == 0 || av->height == 0) {
3847             av->width = 160;
3848             av->height = 128;
3849         }
3850         /* Bitrate tolerance is less for streaming */
3851         if (av->bit_rate_tolerance == 0)
3852             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3853                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3854         if (av->qmin == 0)
3855             av->qmin = 3;
3856         if (av->qmax == 0)
3857             av->qmax = 31;
3858         if (av->max_qdiff == 0)
3859             av->max_qdiff = 3;
3860         av->qcompress = 0.5;
3861         av->qblur = 0.5;
3862
3863         if (!av->nsse_weight)
3864             av->nsse_weight = 8;
3865
3866         av->frame_skip_cmp = FF_CMP_DCTMAX;
3867         if (!av->me_method)
3868             av->me_method = ME_EPZS;
3869         av->rc_buffer_aggressivity = 1.0;
3870
3871         if (!av->rc_eq)
3872             av->rc_eq = "tex^qComp";
3873         if (!av->i_quant_factor)
3874             av->i_quant_factor = -0.8;
3875         if (!av->b_quant_factor)
3876             av->b_quant_factor = 1.25;
3877         if (!av->b_quant_offset)
3878             av->b_quant_offset = 1.25;
3879         if (!av->rc_max_rate)
3880             av->rc_max_rate = av->bit_rate * 2;
3881
3882         if (av->rc_max_rate && !av->rc_buffer_size) {
3883             av->rc_buffer_size = av->rc_max_rate;
3884         }
3885
3886
3887         break;
3888     default:
3889         abort();
3890     }
3891
3892     st = av_mallocz(sizeof(AVStream));
3893     if (!st)
3894         return;
3895     st->codec = avcodec_alloc_context();
3896     stream->streams[stream->nb_streams++] = st;
3897     memcpy(st->codec, av, sizeof(AVCodecContext));
3898 }
3899
3900 static enum CodecID opt_audio_codec(const char *arg)
3901 {
3902     AVCodec *p= avcodec_find_encoder_by_name(arg);
3903
3904     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3905         return CODEC_ID_NONE;
3906
3907     return p->id;
3908 }
3909
3910 static enum CodecID opt_video_codec(const char *arg)
3911 {
3912     AVCodec *p= avcodec_find_encoder_by_name(arg);
3913
3914     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3915         return CODEC_ID_NONE;
3916
3917     return p->id;
3918 }
3919
3920 /* simplistic plugin support */
3921
3922 #if HAVE_DLOPEN
3923 static void load_module(const char *filename)
3924 {
3925     void *dll;
3926     void (*init_func)(void);
3927     dll = dlopen(filename, RTLD_NOW);
3928     if (!dll) {
3929         fprintf(stderr, "Could not load module '%s' - %s\n",
3930                 filename, dlerror());
3931         return;
3932     }
3933
3934     init_func = dlsym(dll, "ffserver_module_init");
3935     if (!init_func) {
3936         fprintf(stderr,
3937                 "%s: init function 'ffserver_module_init()' not found\n",
3938                 filename);
3939         dlclose(dll);
3940     }
3941
3942     init_func();
3943 }
3944 #endif
3945
3946 static int ffserver_opt_default(const char *opt, const char *arg,
3947                        AVCodecContext *avctx, int type)
3948 {
3949     int ret = 0;
3950     const AVOption *o = av_find_opt(avctx, opt, NULL, type, type);
3951     if(o)
3952         ret = av_set_string3(avctx, opt, arg, 1, NULL);
3953     return ret;
3954 }
3955
3956 static int ffserver_opt_preset(const char *arg,
3957                        AVCodecContext *avctx, int type,
3958                        enum CodecID *audio_id, enum CodecID *video_id)
3959 {
3960     FILE *f=NULL;
3961     char filename[1000], tmp[1000], tmp2[1000], line[1000];
3962     int ret = 0;
3963     AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3964
3965     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3966                               codec ? codec->name : NULL))) {
3967         fprintf(stderr, "File for preset '%s' not found\n", arg);
3968         return 1;
3969     }
3970
3971     while(!feof(f)){
3972         int e= fscanf(f, "%999[^\n]\n", line) - 1;
3973         if(line[0] == '#' && !e)
3974             continue;
3975         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3976         if(e){
3977             fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3978             ret = 1;
3979             break;
3980         }
3981         if(!strcmp(tmp, "acodec")){
3982             *audio_id = opt_audio_codec(tmp2);
3983         }else if(!strcmp(tmp, "vcodec")){
3984             *video_id = opt_video_codec(tmp2);
3985         }else if(!strcmp(tmp, "scodec")){
3986             /* opt_subtitle_codec(tmp2); */
3987         }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
3988             fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3989             ret = 1;
3990             break;
3991         }
3992     }
3993
3994     fclose(f);
3995
3996     return ret;
3997 }
3998
3999 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
4000                                              const char *mime_type)
4001 {
4002     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
4003
4004     if (fmt) {
4005         AVOutputFormat *stream_fmt;
4006         char stream_format_name[64];
4007
4008         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4009         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4010
4011         if (stream_fmt)
4012             fmt = stream_fmt;
4013     }
4014
4015     return fmt;
4016 }
4017
4018 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4019 {
4020     va_list vl;
4021     va_start(vl, fmt);
4022     fprintf(stderr, "%s:%d: ", filename, line_num);
4023     vfprintf(stderr, fmt, vl);
4024     va_end(vl);
4025
4026     (*errors)++;
4027 }
4028
4029 static int parse_ffconfig(const char *filename)
4030 {
4031     FILE *f;
4032     char line[1024];
4033     char cmd[64];
4034     char arg[1024];
4035     const char *p;
4036     int val, errors, line_num;
4037     FFStream **last_stream, *stream, *redirect;
4038     FFStream **last_feed, *feed, *s;
4039     AVCodecContext audio_enc, video_enc;
4040     enum CodecID audio_id, video_id;
4041
4042     f = fopen(filename, "r");
4043     if (!f) {
4044         perror(filename);
4045         return -1;
4046     }
4047
4048     errors = 0;
4049     line_num = 0;
4050     first_stream = NULL;
4051     last_stream = &first_stream;
4052     first_feed = NULL;
4053     last_feed = &first_feed;
4054     stream = NULL;
4055     feed = NULL;
4056     redirect = NULL;
4057     audio_id = CODEC_ID_NONE;
4058     video_id = CODEC_ID_NONE;
4059
4060 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4061     for(;;) {
4062         if (fgets(line, sizeof(line), f) == NULL)
4063             break;
4064         line_num++;
4065         p = line;
4066         while (isspace(*p))
4067             p++;
4068         if (*p == '\0' || *p == '#')
4069             continue;
4070
4071         get_arg(cmd, sizeof(cmd), &p);
4072
4073         if (!strcasecmp(cmd, "Port")) {
4074             get_arg(arg, sizeof(arg), &p);
4075             val = atoi(arg);
4076             if (val < 1 || val > 65536) {
4077                 ERROR("Invalid_port: %s\n", arg);
4078             }
4079             my_http_addr.sin_port = htons(val);
4080         } else if (!strcasecmp(cmd, "BindAddress")) {
4081             get_arg(arg, sizeof(arg), &p);
4082             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4083                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4084             }
4085         } else if (!strcasecmp(cmd, "NoDaemon")) {
4086             ffserver_daemon = 0;
4087         } else if (!strcasecmp(cmd, "RTSPPort")) {
4088             get_arg(arg, sizeof(arg), &p);
4089             val = atoi(arg);
4090             if (val < 1 || val > 65536) {
4091                 ERROR("%s:%d: Invalid port: %s\n", arg);
4092             }
4093             my_rtsp_addr.sin_port = htons(atoi(arg));
4094         } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
4095             get_arg(arg, sizeof(arg), &p);
4096             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4097                 ERROR("Invalid host/IP address: %s\n", arg);
4098             }
4099         } else if (!strcasecmp(cmd, "MaxHTTPConnections")) {
4100             get_arg(arg, sizeof(arg), &p);
4101             val = atoi(arg);
4102             if (val < 1 || val > 65536) {
4103                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4104             }
4105             nb_max_http_connections = val;
4106         } else if (!strcasecmp(cmd, "MaxClients")) {
4107             get_arg(arg, sizeof(arg), &p);
4108             val = atoi(arg);
4109             if (val < 1 || val > nb_max_http_connections) {
4110                 ERROR("Invalid MaxClients: %s\n", arg);
4111             } else {
4112                 nb_max_connections = val;
4113             }
4114         } else if (!strcasecmp(cmd, "MaxBandwidth")) {
4115             int64_t llval;
4116             get_arg(arg, sizeof(arg), &p);
4117             llval = atoll(arg);
4118             if (llval < 10 || llval > 10000000) {
4119                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4120             } else
4121                 max_bandwidth = llval;
4122         } else if (!strcasecmp(cmd, "CustomLog")) {
4123             if (!ffserver_debug)
4124                 get_arg(logfilename, sizeof(logfilename), &p);
4125         } else if (!strcasecmp(cmd, "<Feed")) {
4126             /*********************************************/
4127             /* Feed related options */
4128             char *q;
4129             if (stream || feed) {
4130                 ERROR("Already in a tag\n");
4131             } else {
4132                 feed = av_mallocz(sizeof(FFStream));
4133                 get_arg(feed->filename, sizeof(feed->filename), &p);
4134                 q = strrchr(feed->filename, '>');
4135                 if (*q)
4136                     *q = '\0';
4137
4138                 for (s = first_feed; s; s = s->next) {
4139                     if (!strcmp(feed->filename, s->filename)) {
4140                         ERROR("Feed '%s' already registered\n", s->filename);
4141                     }
4142                 }
4143
4144                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4145                 /* defaut feed file */
4146                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4147                          "/tmp/%s.ffm", feed->filename);
4148                 feed->feed_max_size = 5 * 1024 * 1024;
4149                 feed->is_feed = 1;
4150                 feed->feed = feed; /* self feeding :-) */
4151
4152                 /* add in stream list */
4153                 *last_stream = feed;
4154                 last_stream = &feed->next;
4155                 /* add in feed list */
4156                 *last_feed = feed;
4157                 last_feed = &feed->next_feed;
4158             }
4159         } else if (!strcasecmp(cmd, "Launch")) {
4160             if (feed) {
4161                 int i;
4162
4163                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4164
4165                 for (i = 0; i < 62; i++) {
4166                     get_arg(arg, sizeof(arg), &p);
4167                     if (!arg[0])
4168                         break;
4169
4170                     feed->child_argv[i] = av_strdup(arg);
4171                 }
4172
4173                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4174
4175                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4176                     "http://%s:%d/%s",
4177                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4178                     inet_ntoa(my_http_addr.sin_addr),
4179                     ntohs(my_http_addr.sin_port), feed->filename);
4180             }
4181         } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
4182             if (feed) {
4183                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4184                 feed->readonly = 1;
4185             } else if (stream) {
4186                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4187             }
4188         } else if (!strcasecmp(cmd, "File")) {
4189             if (feed) {
4190                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4191             } else if (stream)
4192                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4193         } else if (!strcasecmp(cmd, "Truncate")) {
4194             if (feed) {
4195                 get_arg(arg, sizeof(arg), &p);
4196                 feed->truncate = strtod(arg, NULL);
4197             }
4198         } else if (!strcasecmp(cmd, "FileMaxSize")) {
4199             if (feed) {
4200                 char *p1;
4201                 double fsize;
4202
4203                 get_arg(arg, sizeof(arg), &p);
4204                 p1 = arg;
4205                 fsize = strtod(p1, &p1);
4206                 switch(toupper(*p1)) {
4207                 case 'K':
4208                     fsize *= 1024;
4209                     break;
4210                 case 'M':
4211                     fsize *= 1024 * 1024;
4212                     break;
4213                 case 'G':
4214                     fsize *= 1024 * 1024 * 1024;
4215                     break;
4216                 }
4217                 feed->feed_max_size = (int64_t)fsize;
4218                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4219                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4220                 }
4221             }
4222         } else if (!strcasecmp(cmd, "</Feed>")) {
4223             if (!feed) {
4224                 ERROR("No corresponding <Feed> for </Feed>\n");
4225             }
4226             feed = NULL;
4227         } else if (!strcasecmp(cmd, "<Stream")) {
4228             /*********************************************/
4229             /* Stream related options */
4230             char *q;
4231             if (stream || feed) {
4232                 ERROR("Already in a tag\n");
4233             } else {
4234                 FFStream *s;
4235                 stream = av_mallocz(sizeof(FFStream));
4236                 get_arg(stream->filename, sizeof(stream->filename), &p);
4237                 q = strrchr(stream->filename, '>');
4238                 if (*q)
4239                     *q = '\0';
4240
4241                 for (s = first_stream; s; s = s->next) {
4242                     if (!strcmp(stream->filename, s->filename)) {
4243                         ERROR("Stream '%s' already registered\n", s->filename);
4244                     }
4245                 }
4246
4247                 stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4248                 avcodec_get_context_defaults2(&video_enc, AVMEDIA_TYPE_VIDEO);
4249                 avcodec_get_context_defaults2(&audio_enc, AVMEDIA_TYPE_AUDIO);
4250                 audio_id = CODEC_ID_NONE;
4251                 video_id = CODEC_ID_NONE;
4252                 if (stream->fmt) {
4253                     audio_id = stream->fmt->audio_codec;
4254                     video_id = stream->fmt->video_codec;
4255                 }
4256
4257                 *last_stream = stream;
4258                 last_stream = &stream->next;
4259             }
4260         } else if (!strcasecmp(cmd, "Feed")) {
4261             get_arg(arg, sizeof(arg), &p);
4262             if (stream) {
4263                 FFStream *sfeed;
4264
4265                 sfeed = first_feed;
4266                 while (sfeed != NULL) {
4267                     if (!strcmp(sfeed->filename, arg))
4268                         break;
4269                     sfeed = sfeed->next_feed;
4270                 }
4271                 if (!sfeed)
4272                     ERROR("feed '%s' not defined\n", arg);
4273                 else
4274                     stream->feed = sfeed;
4275             }
4276         } else if (!strcasecmp(cmd, "Format")) {
4277             get_arg(arg, sizeof(arg), &p);
4278             if (stream) {
4279                 if (!strcmp(arg, "status")) {
4280                     stream->stream_type = STREAM_TYPE_STATUS;
4281                     stream->fmt = NULL;
4282                 } else {
4283                     stream->stream_type = STREAM_TYPE_LIVE;
4284                     /* jpeg cannot be used here, so use single frame jpeg */
4285                     if (!strcmp(arg, "jpeg"))
4286                         strcpy(arg, "mjpeg");
4287                     stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4288                     if (!stream->fmt) {
4289                         ERROR("Unknown Format: %s\n", arg);
4290                     }
4291                 }
4292                 if (stream->fmt) {
4293                     audio_id = stream->fmt->audio_codec;
4294                     video_id = stream->fmt->video_codec;
4295                 }
4296             }
4297         } else if (!strcasecmp(cmd, "InputFormat")) {
4298             get_arg(arg, sizeof(arg), &p);
4299             if (stream) {
4300                 stream->ifmt = av_find_input_format(arg);
4301                 if (!stream->ifmt) {
4302                     ERROR("Unknown input format: %s\n", arg);
4303                 }
4304             }
4305         } else if (!strcasecmp(cmd, "FaviconURL")) {
4306             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4307                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4308             } else {
4309                 ERROR("FaviconURL only permitted for status streams\n");
4310             }
4311         } else if (!strcasecmp(cmd, "Author")) {
4312             if (stream)
4313                 get_arg(stream->author, sizeof(stream->author), &p);
4314         } else if (!strcasecmp(cmd, "Comment")) {
4315             if (stream)
4316                 get_arg(stream->comment, sizeof(stream->comment), &p);
4317         } else if (!strcasecmp(cmd, "Copyright")) {
4318             if (stream)
4319                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4320         } else if (!strcasecmp(cmd, "Title")) {
4321             if (stream)
4322                 get_arg(stream->title, sizeof(stream->title), &p);
4323         } else if (!strcasecmp(cmd, "Preroll")) {
4324             get_arg(arg, sizeof(arg), &p);
4325             if (stream)
4326                 stream->prebuffer = atof(arg) * 1000;
4327         } else if (!strcasecmp(cmd, "StartSendOnKey")) {
4328             if (stream)
4329                 stream->send_on_key = 1;
4330         } else if (!strcasecmp(cmd, "AudioCodec")) {
4331             get_arg(arg, sizeof(arg), &p);
4332             audio_id = opt_audio_codec(arg);
4333             if (audio_id == CODEC_ID_NONE) {
4334                 ERROR("Unknown AudioCodec: %s\n", arg);
4335             }
4336         } else if (!strcasecmp(cmd, "VideoCodec")) {
4337             get_arg(arg, sizeof(arg), &p);
4338             video_id = opt_video_codec(arg);
4339             if (video_id == CODEC_ID_NONE) {
4340                 ERROR("Unknown VideoCodec: %s\n", arg);
4341             }
4342         } else if (!strcasecmp(cmd, "MaxTime")) {
4343             get_arg(arg, sizeof(arg), &p);
4344             if (stream)
4345                 stream->max_time = atof(arg) * 1000;
4346         } else if (!strcasecmp(cmd, "AudioBitRate")) {
4347             get_arg(arg, sizeof(arg), &p);
4348             if (stream)
4349                 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4350         } else if (!strcasecmp(cmd, "AudioChannels")) {
4351             get_arg(arg, sizeof(arg), &p);
4352             if (stream)
4353                 audio_enc.channels = atoi(arg);
4354         } else if (!strcasecmp(cmd, "AudioSampleRate")) {
4355             get_arg(arg, sizeof(arg), &p);
4356             if (stream)
4357                 audio_enc.sample_rate = atoi(arg);
4358         } else if (!strcasecmp(cmd, "AudioQuality")) {
4359             get_arg(arg, sizeof(arg), &p);
4360             if (stream) {
4361 //                audio_enc.quality = atof(arg) * 1000;
4362             }
4363         } else if (!strcasecmp(cmd, "VideoBitRateRange")) {
4364             if (stream) {
4365                 int minrate, maxrate;
4366
4367                 get_arg(arg, sizeof(arg), &p);
4368
4369                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4370                     video_enc.rc_min_rate = minrate * 1000;
4371                     video_enc.rc_max_rate = maxrate * 1000;
4372                 } else {
4373                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4374                 }
4375             }
4376         } else if (!strcasecmp(cmd, "Debug")) {
4377             if (stream) {
4378                 get_arg(arg, sizeof(arg), &p);
4379                 video_enc.debug = strtol(arg,0,0);
4380             }
4381         } else if (!strcasecmp(cmd, "Strict")) {
4382             if (stream) {
4383                 get_arg(arg, sizeof(arg), &p);
4384                 video_enc.strict_std_compliance = atoi(arg);
4385             }
4386         } else if (!strcasecmp(cmd, "VideoBufferSize")) {
4387             if (stream) {
4388                 get_arg(arg, sizeof(arg), &p);
4389                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4390             }
4391         } else if (!strcasecmp(cmd, "VideoBitRateTolerance")) {
4392             if (stream) {
4393                 get_arg(arg, sizeof(arg), &p);
4394                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4395             }
4396         } else if (!strcasecmp(cmd, "VideoBitRate")) {
4397             get_arg(arg, sizeof(arg), &p);
4398             if (stream) {
4399                 video_enc.bit_rate = atoi(arg) * 1000;
4400             }
4401         } else if (!strcasecmp(cmd, "VideoSize")) {
4402             get_arg(arg, sizeof(arg), &p);
4403             if (stream) {
4404                 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4405                 if ((video_enc.width % 16) != 0 ||
4406                     (video_enc.height % 16) != 0) {
4407                     ERROR("Image size must be a multiple of 16\n");
4408                 }
4409             }
4410         } else if (!strcasecmp(cmd, "VideoFrameRate")) {
4411             get_arg(arg, sizeof(arg), &p);
4412             if (stream) {
4413                 AVRational frame_rate;
4414                 if (av_parse_video_rate(&frame_rate, arg) < 0) {
4415                     ERROR("Incorrect frame rate: %s\n", arg);
4416                 } else {
4417                     video_enc.time_base.num = frame_rate.den;
4418                     video_enc.time_base.den = frame_rate.num;
4419                 }
4420             }
4421         } else if (!strcasecmp(cmd, "VideoGopSize")) {
4422             get_arg(arg, sizeof(arg), &p);
4423             if (stream)
4424                 video_enc.gop_size = atoi(arg);
4425         } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
4426             if (stream)
4427                 video_enc.gop_size = 1;
4428         } else if (!strcasecmp(cmd, "VideoHighQuality")) {
4429             if (stream)
4430                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4431         } else if (!strcasecmp(cmd, "Video4MotionVector")) {
4432             if (stream) {
4433                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4434                 video_enc.flags |= CODEC_FLAG_4MV;
4435             }
4436         } else if (!strcasecmp(cmd, "AVOptionVideo") ||
4437                    !strcasecmp(cmd, "AVOptionAudio")) {
4438             char arg2[1024];
4439             AVCodecContext *avctx;
4440             int type;
4441             get_arg(arg, sizeof(arg), &p);
4442             get_arg(arg2, sizeof(arg2), &p);
4443             if (!strcasecmp(cmd, "AVOptionVideo")) {
4444                 avctx = &video_enc;
4445                 type = AV_OPT_FLAG_VIDEO_PARAM;
4446             } else {
4447                 avctx = &audio_enc;
4448                 type = AV_OPT_FLAG_AUDIO_PARAM;
4449             }
4450             if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4451                 ERROR("AVOption error: %s %s\n", arg, arg2);
4452             }
4453         } else if (!strcasecmp(cmd, "AVPresetVideo") ||
4454                    !strcasecmp(cmd, "AVPresetAudio")) {
4455             AVCodecContext *avctx;
4456             int type;
4457             get_arg(arg, sizeof(arg), &p);
4458             if (!strcasecmp(cmd, "AVPresetVideo")) {
4459                 avctx = &video_enc;
4460                 video_enc.codec_id = video_id;
4461                 type = AV_OPT_FLAG_VIDEO_PARAM;
4462             } else {
4463                 avctx = &audio_enc;
4464                 audio_enc.codec_id = audio_id;
4465                 type = AV_OPT_FLAG_AUDIO_PARAM;
4466             }
4467             if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4468                 ERROR("AVPreset error: %s\n", arg);
4469             }
4470         } else if (!strcasecmp(cmd, "VideoTag")) {
4471             get_arg(arg, sizeof(arg), &p);
4472             if ((strlen(arg) == 4) && stream)
4473                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4474         } else if (!strcasecmp(cmd, "BitExact")) {
4475             if (stream)
4476                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4477         } else if (!strcasecmp(cmd, "DctFastint")) {
4478             if (stream)
4479                 video_enc.dct_algo  = FF_DCT_FASTINT;
4480         } else if (!strcasecmp(cmd, "IdctSimple")) {
4481             if (stream)
4482                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4483         } else if (!strcasecmp(cmd, "Qscale")) {
4484             get_arg(arg, sizeof(arg), &p);
4485             if (stream) {
4486                 video_enc.flags |= CODEC_FLAG_QSCALE;
4487                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4488             }
4489         } else if (!strcasecmp(cmd, "VideoQDiff")) {
4490             get_arg(arg, sizeof(arg), &p);
4491             if (stream) {
4492                 video_enc.max_qdiff = atoi(arg);
4493                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4494                     ERROR("VideoQDiff out of range\n");
4495                 }
4496             }
4497         } else if (!strcasecmp(cmd, "VideoQMax")) {
4498             get_arg(arg, sizeof(arg), &p);
4499             if (stream) {
4500                 video_enc.qmax = atoi(arg);
4501                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4502                     ERROR("VideoQMax out of range\n");
4503                 }
4504             }
4505         } else if (!strcasecmp(cmd, "VideoQMin")) {
4506             get_arg(arg, sizeof(arg), &p);
4507             if (stream) {
4508                 video_enc.qmin = atoi(arg);
4509                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4510                     ERROR("VideoQMin out of range\n");
4511                 }
4512             }
4513         } else if (!strcasecmp(cmd, "LumaElim")) {
4514             get_arg(arg, sizeof(arg), &p);
4515             if (stream)
4516                 video_enc.luma_elim_threshold = atoi(arg);
4517         } else if (!strcasecmp(cmd, "ChromaElim")) {
4518             get_arg(arg, sizeof(arg), &p);
4519             if (stream)
4520                 video_enc.chroma_elim_threshold = atoi(arg);
4521         } else if (!strcasecmp(cmd, "LumiMask")) {
4522             get_arg(arg, sizeof(arg), &p);
4523             if (stream)
4524                 video_enc.lumi_masking = atof(arg);
4525         } else if (!strcasecmp(cmd, "DarkMask")) {
4526             get_arg(arg, sizeof(arg), &p);
4527             if (stream)
4528                 video_enc.dark_masking = atof(arg);
4529         } else if (!strcasecmp(cmd, "NoVideo")) {
4530             video_id = CODEC_ID_NONE;
4531         } else if (!strcasecmp(cmd, "NoAudio")) {
4532             audio_id = CODEC_ID_NONE;
4533         } else if (!strcasecmp(cmd, "ACL")) {
4534             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4535         } else if (!strcasecmp(cmd, "DynamicACL")) {
4536             if (stream) {
4537                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4538             }
4539         } else if (!strcasecmp(cmd, "RTSPOption")) {
4540             get_arg(arg, sizeof(arg), &p);
4541             if (stream) {
4542                 av_freep(&stream->rtsp_option);
4543                 stream->rtsp_option = av_strdup(arg);
4544             }
4545         } else if (!strcasecmp(cmd, "MulticastAddress")) {
4546             get_arg(arg, sizeof(arg), &p);
4547             if (stream) {
4548                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4549                     ERROR("Invalid host/IP address: %s\n", arg);
4550                 }
4551                 stream->is_multicast = 1;
4552                 stream->loop = 1; /* default is looping */
4553             }
4554         } else if (!strcasecmp(cmd, "MulticastPort")) {
4555             get_arg(arg, sizeof(arg), &p);
4556             if (stream)
4557                 stream->multicast_port = atoi(arg);
4558         } else if (!strcasecmp(cmd, "MulticastTTL")) {
4559             get_arg(arg, sizeof(arg), &p);
4560             if (stream)
4561                 stream->multicast_ttl = atoi(arg);
4562         } else if (!strcasecmp(cmd, "NoLoop")) {
4563             if (stream)
4564                 stream->loop = 0;
4565         } else if (!strcasecmp(cmd, "</Stream>")) {
4566             if (!stream) {
4567                 ERROR("No corresponding <Stream> for </Stream>\n");
4568             } else {
4569                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4570                     if (audio_id != CODEC_ID_NONE) {
4571                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4572                         audio_enc.codec_id = audio_id;
4573                         add_codec(stream, &audio_enc);
4574                     }
4575                     if (video_id != CODEC_ID_NONE) {
4576                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4577                         video_enc.codec_id = video_id;
4578                         add_codec(stream, &video_enc);
4579                     }
4580                 }
4581                 stream = NULL;
4582             }
4583         } else if (!strcasecmp(cmd, "<Redirect")) {
4584             /*********************************************/
4585             char *q;
4586             if (stream || feed || redirect) {
4587                 ERROR("Already in a tag\n");
4588             } else {
4589                 redirect = av_mallocz(sizeof(FFStream));
4590                 *last_stream = redirect;
4591                 last_stream = &redirect->next;
4592
4593                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4594                 q = strrchr(redirect->filename, '>');
4595                 if (*q)
4596                     *q = '\0';
4597                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4598             }
4599         } else if (!strcasecmp(cmd, "URL")) {
4600             if (redirect)
4601                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4602         } else if (!strcasecmp(cmd, "</Redirect>")) {
4603             if (!redirect) {
4604                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4605             } else {
4606                 if (!redirect->feed_filename[0]) {
4607                     ERROR("No URL found for <Redirect>\n");
4608                 }
4609                 redirect = NULL;
4610             }
4611         } else if (!strcasecmp(cmd, "LoadModule")) {
4612             get_arg(arg, sizeof(arg), &p);
4613 #if HAVE_DLOPEN
4614             load_module(arg);
4615 #else
4616             ERROR("Module support not compiled into this version: '%s'\n", arg);
4617 #endif
4618         } else {
4619             ERROR("Incorrect keyword: '%s'\n", cmd);
4620         }
4621     }
4622 #undef ERROR
4623
4624     fclose(f);
4625     if (errors)
4626         return -1;
4627     else
4628         return 0;
4629 }
4630
4631 static void handle_child_exit(int sig)
4632 {
4633     pid_t pid;
4634     int status;
4635
4636     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4637         FFStream *feed;
4638
4639         for (feed = first_feed; feed; feed = feed->next) {
4640             if (feed->pid == pid) {
4641                 int uptime = time(0) - feed->pid_start;
4642
4643                 feed->pid = 0;
4644                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4645
4646                 if (uptime < 30)
4647                     /* Turn off any more restarts */
4648                     feed->child_argv = 0;
4649             }
4650         }
4651     }
4652
4653     need_to_start_children = 1;
4654 }
4655
4656 static void opt_debug(void)
4657 {
4658     ffserver_debug = 1;
4659     ffserver_daemon = 0;
4660     logfilename[0] = '-';
4661 }
4662
4663 static void show_help(void)
4664 {
4665     printf("usage: ffserver [options]\n"
4666            "Hyper fast multi format Audio/Video streaming server\n");
4667     printf("\n");
4668     show_help_options(options, "Main options:\n", 0, 0);
4669 }
4670
4671 static const OptionDef options[] = {
4672 #include "cmdutils_common_opts.h"
4673     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4674     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4675     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4676     { NULL },
4677 };
4678
4679 int main(int argc, char **argv)
4680 {
4681     struct sigaction sigact;
4682
4683     av_register_all();
4684
4685     show_banner();
4686
4687     my_program_name = argv[0];
4688     my_program_dir = getcwd(0, 0);
4689     ffserver_daemon = 1;
4690
4691     parse_options(argc, argv, options, NULL);
4692
4693     unsetenv("http_proxy");             /* Kill the http_proxy */
4694
4695     av_lfg_init(&random_state, av_get_random_seed());
4696
4697     memset(&sigact, 0, sizeof(sigact));
4698     sigact.sa_handler = handle_child_exit;
4699     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4700     sigaction(SIGCHLD, &sigact, 0);
4701
4702     if (parse_ffconfig(config_filename) < 0) {
4703         fprintf(stderr, "Incorrect config file - exiting.\n");
4704         exit(1);
4705     }
4706
4707     /* open log file if needed */
4708     if (logfilename[0] != '\0') {
4709         if (!strcmp(logfilename, "-"))
4710             logfile = stdout;
4711         else
4712             logfile = fopen(logfilename, "a");
4713         av_log_set_callback(http_av_log);
4714     }
4715
4716     build_file_streams();
4717
4718     build_feed_streams();
4719
4720     compute_bandwidth();
4721
4722     /* put the process in background and detach it from its TTY */
4723     if (ffserver_daemon) {
4724         int pid;
4725
4726         pid = fork();
4727         if (pid < 0) {
4728             perror("fork");
4729             exit(1);
4730         } else if (pid > 0) {
4731             /* parent : exit */
4732             exit(0);
4733         } else {
4734             /* child */
4735             setsid();
4736             close(0);
4737             open("/dev/null", O_RDWR);
4738             if (strcmp(logfilename, "-") != 0) {
4739                 close(1);
4740                 dup(0);
4741             }
4742             close(2);
4743             dup(0);
4744         }
4745     }
4746
4747     /* signal init */
4748     signal(SIGPIPE, SIG_IGN);
4749
4750     if (ffserver_daemon)
4751         chdir("/");
4752
4753     if (http_server() < 0) {
4754         http_log("Could not start server\n");
4755         exit(1);
4756     }
4757
4758     return 0;
4759 }