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