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