]> git.sesse.net Git - ffmpeg/blob - avserver.c
proresenc: multithreaded quantiser search
[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         ftruncate(c->feed_fd, FFM_PACKET_SIZE);
2576         http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2577     } else {
2578         if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2579             http_log("Error reading write index from feed file: %s\n", strerror(errno));
2580             return -1;
2581         }
2582     }
2583
2584     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2585     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2586     lseek(fd, 0, SEEK_SET);
2587
2588     /* init buffer input */
2589     c->buffer_ptr = c->buffer;
2590     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2591     c->stream->feed_opened = 1;
2592     c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2593     return 0;
2594 }
2595
2596 static int http_receive_data(HTTPContext *c)
2597 {
2598     HTTPContext *c1;
2599     int len, loop_run = 0;
2600
2601     while (c->chunked_encoding && !c->chunk_size &&
2602            c->buffer_end > c->buffer_ptr) {
2603         /* read chunk header, if present */
2604         len = recv(c->fd, c->buffer_ptr, 1, 0);
2605
2606         if (len < 0) {
2607             if (ff_neterrno() != AVERROR(EAGAIN) &&
2608                 ff_neterrno() != AVERROR(EINTR))
2609                 /* error : close connection */
2610                 goto fail;
2611             return 0;
2612         } else if (len == 0) {
2613             /* end of connection : close it */
2614             goto fail;
2615         } else if (c->buffer_ptr - c->buffer >= 2 &&
2616                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2617             c->chunk_size = strtol(c->buffer, 0, 16);
2618             if (c->chunk_size == 0) // end of stream
2619                 goto fail;
2620             c->buffer_ptr = c->buffer;
2621             break;
2622         } else if (++loop_run > 10) {
2623             /* no chunk header, abort */
2624             goto fail;
2625         } else {
2626             c->buffer_ptr++;
2627         }
2628     }
2629
2630     if (c->buffer_end > c->buffer_ptr) {
2631         len = recv(c->fd, c->buffer_ptr,
2632                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2633         if (len < 0) {
2634             if (ff_neterrno() != AVERROR(EAGAIN) &&
2635                 ff_neterrno() != AVERROR(EINTR))
2636                 /* error : close connection */
2637                 goto fail;
2638         } else if (len == 0)
2639             /* end of connection : close it */
2640             goto fail;
2641         else {
2642             c->chunk_size -= len;
2643             c->buffer_ptr += len;
2644             c->data_count += len;
2645             update_datarate(&c->datarate, c->data_count);
2646         }
2647     }
2648
2649     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2650         if (c->buffer[0] != 'f' ||
2651             c->buffer[1] != 'm') {
2652             http_log("Feed stream has become desynchronized -- disconnecting\n");
2653             goto fail;
2654         }
2655     }
2656
2657     if (c->buffer_ptr >= c->buffer_end) {
2658         FFStream *feed = c->stream;
2659         /* a packet has been received : write it in the store, except
2660            if header */
2661         if (c->data_count > FFM_PACKET_SIZE) {
2662
2663             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2664             /* XXX: use llseek or url_seek */
2665             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2666             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2667                 http_log("Error writing to feed file: %s\n", strerror(errno));
2668                 goto fail;
2669             }
2670
2671             feed->feed_write_index += FFM_PACKET_SIZE;
2672             /* update file size */
2673             if (feed->feed_write_index > c->stream->feed_size)
2674                 feed->feed_size = feed->feed_write_index;
2675
2676             /* handle wrap around if max file size reached */
2677             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2678                 feed->feed_write_index = FFM_PACKET_SIZE;
2679
2680             /* write index */
2681             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2682                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2683                 goto fail;
2684             }
2685
2686             /* wake up any waiting connections */
2687             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2688                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2689                     c1->stream->feed == c->stream->feed)
2690                     c1->state = HTTPSTATE_SEND_DATA;
2691             }
2692         } else {
2693             /* We have a header in our hands that contains useful data */
2694             AVFormatContext *s = avformat_alloc_context();
2695             AVIOContext *pb;
2696             AVInputFormat *fmt_in;
2697             int i;
2698
2699             if (!s)
2700                 goto fail;
2701
2702             /* use feed output format name to find corresponding input format */
2703             fmt_in = av_find_input_format(feed->fmt->name);
2704             if (!fmt_in)
2705                 goto fail;
2706
2707             pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2708                                     0, NULL, NULL, NULL, NULL);
2709             pb->seekable = 0;
2710
2711             s->pb = pb;
2712             if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2713                 av_free(pb);
2714                 goto fail;
2715             }
2716
2717             /* Now we have the actual streams */
2718             if (s->nb_streams != feed->nb_streams) {
2719                 avformat_close_input(&s);
2720                 av_free(pb);
2721                 http_log("Feed '%s' stream number does not match registered feed\n",
2722                          c->stream->feed_filename);
2723                 goto fail;
2724             }
2725
2726             for (i = 0; i < s->nb_streams; i++) {
2727                 AVStream *fst = feed->streams[i];
2728                 AVStream *st = s->streams[i];
2729                 avcodec_copy_context(fst->codec, st->codec);
2730             }
2731
2732             avformat_close_input(&s);
2733             av_free(pb);
2734         }
2735         c->buffer_ptr = c->buffer;
2736     }
2737
2738     return 0;
2739  fail:
2740     c->stream->feed_opened = 0;
2741     close(c->feed_fd);
2742     /* wake up any waiting connections to stop waiting for feed */
2743     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2744         if (c1->state == HTTPSTATE_WAIT_FEED &&
2745             c1->stream->feed == c->stream->feed)
2746             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2747     }
2748     return -1;
2749 }
2750
2751 /********************************************************************/
2752 /* RTSP handling */
2753
2754 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2755 {
2756     const char *str;
2757     time_t ti;
2758     struct tm *tm;
2759     char buf2[32];
2760
2761     switch(error_number) {
2762     case RTSP_STATUS_OK:
2763         str = "OK";
2764         break;
2765     case RTSP_STATUS_METHOD:
2766         str = "Method Not Allowed";
2767         break;
2768     case RTSP_STATUS_BANDWIDTH:
2769         str = "Not Enough Bandwidth";
2770         break;
2771     case RTSP_STATUS_SESSION:
2772         str = "Session Not Found";
2773         break;
2774     case RTSP_STATUS_STATE:
2775         str = "Method Not Valid in This State";
2776         break;
2777     case RTSP_STATUS_AGGREGATE:
2778         str = "Aggregate operation not allowed";
2779         break;
2780     case RTSP_STATUS_ONLY_AGGREGATE:
2781         str = "Only aggregate operation allowed";
2782         break;
2783     case RTSP_STATUS_TRANSPORT:
2784         str = "Unsupported transport";
2785         break;
2786     case RTSP_STATUS_INTERNAL:
2787         str = "Internal Server Error";
2788         break;
2789     case RTSP_STATUS_SERVICE:
2790         str = "Service Unavailable";
2791         break;
2792     case RTSP_STATUS_VERSION:
2793         str = "RTSP Version not supported";
2794         break;
2795     default:
2796         str = "Unknown Error";
2797         break;
2798     }
2799
2800     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2801     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2802
2803     /* output GMT time */
2804     ti = time(NULL);
2805     tm = gmtime(&ti);
2806     strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2807     avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2808 }
2809
2810 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2811 {
2812     rtsp_reply_header(c, error_number);
2813     avio_printf(c->pb, "\r\n");
2814 }
2815
2816 static int rtsp_parse_request(HTTPContext *c)
2817 {
2818     const char *p, *p1, *p2;
2819     char cmd[32];
2820     char url[1024];
2821     char protocol[32];
2822     char line[1024];
2823     int len;
2824     RTSPMessageHeader header1 = { 0 }, *header = &header1;
2825
2826     c->buffer_ptr[0] = '\0';
2827     p = c->buffer;
2828
2829     get_word(cmd, sizeof(cmd), &p);
2830     get_word(url, sizeof(url), &p);
2831     get_word(protocol, sizeof(protocol), &p);
2832
2833     av_strlcpy(c->method, cmd, sizeof(c->method));
2834     av_strlcpy(c->url, url, sizeof(c->url));
2835     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2836
2837     if (avio_open_dyn_buf(&c->pb) < 0) {
2838         /* XXX: cannot do more */
2839         c->pb = NULL; /* safety */
2840         return -1;
2841     }
2842
2843     /* check version name */
2844     if (strcmp(protocol, "RTSP/1.0") != 0) {
2845         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2846         goto the_end;
2847     }
2848
2849     /* parse each header line */
2850     /* skip to next line */
2851     while (*p != '\n' && *p != '\0')
2852         p++;
2853     if (*p == '\n')
2854         p++;
2855     while (*p != '\0') {
2856         p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2857         if (!p1)
2858             break;
2859         p2 = p1;
2860         if (p2 > p && p2[-1] == '\r')
2861             p2--;
2862         /* skip empty line */
2863         if (p2 == p)
2864             break;
2865         len = p2 - p;
2866         if (len > sizeof(line) - 1)
2867             len = sizeof(line) - 1;
2868         memcpy(line, p, len);
2869         line[len] = '\0';
2870         ff_rtsp_parse_line(header, line, NULL, NULL);
2871         p = p1 + 1;
2872     }
2873
2874     /* handle sequence number */
2875     c->seq = header->seq;
2876
2877     if (!strcmp(cmd, "DESCRIBE"))
2878         rtsp_cmd_describe(c, url);
2879     else if (!strcmp(cmd, "OPTIONS"))
2880         rtsp_cmd_options(c, url);
2881     else if (!strcmp(cmd, "SETUP"))
2882         rtsp_cmd_setup(c, url, header);
2883     else if (!strcmp(cmd, "PLAY"))
2884         rtsp_cmd_play(c, url, header);
2885     else if (!strcmp(cmd, "PAUSE"))
2886         rtsp_cmd_pause(c, url, header);
2887     else if (!strcmp(cmd, "TEARDOWN"))
2888         rtsp_cmd_teardown(c, url, header);
2889     else
2890         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2891
2892  the_end:
2893     len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2894     c->pb = NULL; /* safety */
2895     if (len < 0) {
2896         /* XXX: cannot do more */
2897         return -1;
2898     }
2899     c->buffer_ptr = c->pb_buffer;
2900     c->buffer_end = c->pb_buffer + len;
2901     c->state = RTSPSTATE_SEND_REPLY;
2902     return 0;
2903 }
2904
2905 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2906                                    struct in_addr my_ip)
2907 {
2908     AVFormatContext *avc;
2909     AVStream *avs = NULL;
2910     int i;
2911
2912     avc =  avformat_alloc_context();
2913     if (avc == NULL) {
2914         return -1;
2915     }
2916     av_dict_set(&avc->metadata, "title",
2917                stream->title[0] ? stream->title : "No Title", 0);
2918     avc->nb_streams = stream->nb_streams;
2919     if (stream->is_multicast) {
2920         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2921                  inet_ntoa(stream->multicast_ip),
2922                  stream->multicast_port, stream->multicast_ttl);
2923     } else {
2924         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2925     }
2926
2927     if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2928         !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2929         goto sdp_done;
2930     if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2931         !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2932         goto sdp_done;
2933
2934     for(i = 0; i < stream->nb_streams; i++) {
2935         avc->streams[i] = &avs[i];
2936         avc->streams[i]->codec = stream->streams[i]->codec;
2937     }
2938     *pbuffer = av_mallocz(2048);
2939     av_sdp_create(&avc, 1, *pbuffer, 2048);
2940
2941  sdp_done:
2942     av_free(avc->streams);
2943     av_dict_free(&avc->metadata);
2944     av_free(avc);
2945     av_free(avs);
2946
2947     return strlen(*pbuffer);
2948 }
2949
2950 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2951 {
2952 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2953     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2954     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2955     avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2956     avio_printf(c->pb, "\r\n");
2957 }
2958
2959 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2960 {
2961     FFStream *stream;
2962     char path1[1024];
2963     const char *path;
2964     uint8_t *content;
2965     int content_length, len;
2966     struct sockaddr_in my_addr;
2967
2968     /* find which url is asked */
2969     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2970     path = path1;
2971     if (*path == '/')
2972         path++;
2973
2974     for(stream = first_stream; stream != NULL; stream = stream->next) {
2975         if (!stream->is_feed &&
2976             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2977             !strcmp(path, stream->filename)) {
2978             goto found;
2979         }
2980     }
2981     /* no stream found */
2982     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2983     return;
2984
2985  found:
2986     /* prepare the media description in sdp format */
2987
2988     /* get the host IP */
2989     len = sizeof(my_addr);
2990     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
2991     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
2992     if (content_length < 0) {
2993         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
2994         return;
2995     }
2996     rtsp_reply_header(c, RTSP_STATUS_OK);
2997     avio_printf(c->pb, "Content-Base: %s/\r\n", url);
2998     avio_printf(c->pb, "Content-Type: application/sdp\r\n");
2999     avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3000     avio_printf(c->pb, "\r\n");
3001     avio_write(c->pb, content, content_length);
3002     av_free(content);
3003 }
3004
3005 static HTTPContext *find_rtp_session(const char *session_id)
3006 {
3007     HTTPContext *c;
3008
3009     if (session_id[0] == '\0')
3010         return NULL;
3011
3012     for(c = first_http_ctx; c != NULL; c = c->next) {
3013         if (!strcmp(c->session_id, session_id))
3014             return c;
3015     }
3016     return NULL;
3017 }
3018
3019 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3020 {
3021     RTSPTransportField *th;
3022     int i;
3023
3024     for(i=0;i<h->nb_transports;i++) {
3025         th = &h->transports[i];
3026         if (th->lower_transport == lower_transport)
3027             return th;
3028     }
3029     return NULL;
3030 }
3031
3032 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3033                            RTSPMessageHeader *h)
3034 {
3035     FFStream *stream;
3036     int stream_index, rtp_port, rtcp_port;
3037     char buf[1024];
3038     char path1[1024];
3039     const char *path;
3040     HTTPContext *rtp_c;
3041     RTSPTransportField *th;
3042     struct sockaddr_in dest_addr;
3043     RTSPActionServerSetup setup;
3044
3045     /* find which url is asked */
3046     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3047     path = path1;
3048     if (*path == '/')
3049         path++;
3050
3051     /* now check each stream */
3052     for(stream = first_stream; stream != NULL; stream = stream->next) {
3053         if (!stream->is_feed &&
3054             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3055             /* accept aggregate filenames only if single stream */
3056             if (!strcmp(path, stream->filename)) {
3057                 if (stream->nb_streams != 1) {
3058                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3059                     return;
3060                 }
3061                 stream_index = 0;
3062                 goto found;
3063             }
3064
3065             for(stream_index = 0; stream_index < stream->nb_streams;
3066                 stream_index++) {
3067                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3068                          stream->filename, stream_index);
3069                 if (!strcmp(path, buf))
3070                     goto found;
3071             }
3072         }
3073     }
3074     /* no stream found */
3075     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3076     return;
3077  found:
3078
3079     /* generate session id if needed */
3080     if (h->session_id[0] == '\0')
3081         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3082                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3083
3084     /* find rtp session, and create it if none found */
3085     rtp_c = find_rtp_session(h->session_id);
3086     if (!rtp_c) {
3087         /* always prefer UDP */
3088         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3089         if (!th) {
3090             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3091             if (!th) {
3092                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3093                 return;
3094             }
3095         }
3096
3097         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3098                                    th->lower_transport);
3099         if (!rtp_c) {
3100             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3101             return;
3102         }
3103
3104         /* open input stream */
3105         if (open_input_stream(rtp_c, "") < 0) {
3106             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3107             return;
3108         }
3109     }
3110
3111     /* test if stream is OK (test needed because several SETUP needs
3112        to be done for a given file) */
3113     if (rtp_c->stream != stream) {
3114         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3115         return;
3116     }
3117
3118     /* test if stream is already set up */
3119     if (rtp_c->rtp_ctx[stream_index]) {
3120         rtsp_reply_error(c, RTSP_STATUS_STATE);
3121         return;
3122     }
3123
3124     /* check transport */
3125     th = find_transport(h, rtp_c->rtp_protocol);
3126     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3127                 th->client_port_min <= 0)) {
3128         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3129         return;
3130     }
3131
3132     /* setup default options */
3133     setup.transport_option[0] = '\0';
3134     dest_addr = rtp_c->from_addr;
3135     dest_addr.sin_port = htons(th->client_port_min);
3136
3137     /* setup stream */
3138     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3139         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3140         return;
3141     }
3142
3143     /* now everything is OK, so we can send the connection parameters */
3144     rtsp_reply_header(c, RTSP_STATUS_OK);
3145     /* session ID */
3146     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3147
3148     switch(rtp_c->rtp_protocol) {
3149     case RTSP_LOWER_TRANSPORT_UDP:
3150         rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3151         rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3152         avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3153                     "client_port=%d-%d;server_port=%d-%d",
3154                     th->client_port_min, th->client_port_max,
3155                     rtp_port, rtcp_port);
3156         break;
3157     case RTSP_LOWER_TRANSPORT_TCP:
3158         avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3159                     stream_index * 2, stream_index * 2 + 1);
3160         break;
3161     default:
3162         break;
3163     }
3164     if (setup.transport_option[0] != '\0')
3165         avio_printf(c->pb, ";%s", setup.transport_option);
3166     avio_printf(c->pb, "\r\n");
3167
3168
3169     avio_printf(c->pb, "\r\n");
3170 }
3171
3172
3173 /* find an rtp connection by using the session ID. Check consistency
3174    with filename */
3175 static HTTPContext *find_rtp_session_with_url(const char *url,
3176                                               const char *session_id)
3177 {
3178     HTTPContext *rtp_c;
3179     char path1[1024];
3180     const char *path;
3181     char buf[1024];
3182     int s, len;
3183
3184     rtp_c = find_rtp_session(session_id);
3185     if (!rtp_c)
3186         return NULL;
3187
3188     /* find which url is asked */
3189     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3190     path = path1;
3191     if (*path == '/')
3192         path++;
3193     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3194     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3195       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3196         rtp_c->stream->filename, s);
3197       if(!strncmp(path, buf, sizeof(buf))) {
3198     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3199         return rtp_c;
3200       }
3201     }
3202     len = strlen(path);
3203     if (len > 0 && path[len - 1] == '/' &&
3204         !strncmp(path, rtp_c->stream->filename, len - 1))
3205         return rtp_c;
3206     return NULL;
3207 }
3208
3209 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3210 {
3211     HTTPContext *rtp_c;
3212
3213     rtp_c = find_rtp_session_with_url(url, h->session_id);
3214     if (!rtp_c) {
3215         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3216         return;
3217     }
3218
3219     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3220         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3221         rtp_c->state != HTTPSTATE_READY) {
3222         rtsp_reply_error(c, RTSP_STATUS_STATE);
3223         return;
3224     }
3225
3226     rtp_c->state = HTTPSTATE_SEND_DATA;
3227
3228     /* now everything is OK, so we can send the connection parameters */
3229     rtsp_reply_header(c, RTSP_STATUS_OK);
3230     /* session ID */
3231     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3232     avio_printf(c->pb, "\r\n");
3233 }
3234
3235 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3236 {
3237     HTTPContext *rtp_c;
3238
3239     rtp_c = find_rtp_session_with_url(url, h->session_id);
3240     if (!rtp_c) {
3241         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3242         return;
3243     }
3244
3245     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3246         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3247         rtsp_reply_error(c, RTSP_STATUS_STATE);
3248         return;
3249     }
3250
3251     rtp_c->state = HTTPSTATE_READY;
3252     rtp_c->first_pts = AV_NOPTS_VALUE;
3253     /* now everything is OK, so we can send the connection parameters */
3254     rtsp_reply_header(c, RTSP_STATUS_OK);
3255     /* session ID */
3256     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3257     avio_printf(c->pb, "\r\n");
3258 }
3259
3260 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3261 {
3262     HTTPContext *rtp_c;
3263
3264     rtp_c = find_rtp_session_with_url(url, h->session_id);
3265     if (!rtp_c) {
3266         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3267         return;
3268     }
3269
3270     /* now everything is OK, so we can send the connection parameters */
3271     rtsp_reply_header(c, RTSP_STATUS_OK);
3272     /* session ID */
3273     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3274     avio_printf(c->pb, "\r\n");
3275
3276     /* abort the session */
3277     close_connection(rtp_c);
3278 }
3279
3280
3281 /********************************************************************/
3282 /* RTP handling */
3283
3284 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3285                                        FFStream *stream, const char *session_id,
3286                                        enum RTSPLowerTransport rtp_protocol)
3287 {
3288     HTTPContext *c = NULL;
3289     const char *proto_str;
3290
3291     /* XXX: should output a warning page when coming
3292        close to the connection limit */
3293     if (nb_connections >= nb_max_connections)
3294         goto fail;
3295
3296     /* add a new connection */
3297     c = av_mallocz(sizeof(HTTPContext));
3298     if (!c)
3299         goto fail;
3300
3301     c->fd = -1;
3302     c->poll_entry = NULL;
3303     c->from_addr = *from_addr;
3304     c->buffer_size = IOBUFFER_INIT_SIZE;
3305     c->buffer = av_malloc(c->buffer_size);
3306     if (!c->buffer)
3307         goto fail;
3308     nb_connections++;
3309     c->stream = stream;
3310     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3311     c->state = HTTPSTATE_READY;
3312     c->is_packetized = 1;
3313     c->rtp_protocol = rtp_protocol;
3314
3315     /* protocol is shown in statistics */
3316     switch(c->rtp_protocol) {
3317     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3318         proto_str = "MCAST";
3319         break;
3320     case RTSP_LOWER_TRANSPORT_UDP:
3321         proto_str = "UDP";
3322         break;
3323     case RTSP_LOWER_TRANSPORT_TCP:
3324         proto_str = "TCP";
3325         break;
3326     default:
3327         proto_str = "???";
3328         break;
3329     }
3330     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3331     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3332
3333     current_bandwidth += stream->bandwidth;
3334
3335     c->next = first_http_ctx;
3336     first_http_ctx = c;
3337     return c;
3338
3339  fail:
3340     if (c) {
3341         av_free(c->buffer);
3342         av_free(c);
3343     }
3344     return NULL;
3345 }
3346
3347 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3348    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3349    used. */
3350 static int rtp_new_av_stream(HTTPContext *c,
3351                              int stream_index, struct sockaddr_in *dest_addr,
3352                              HTTPContext *rtsp_c)
3353 {
3354     AVFormatContext *ctx;
3355     AVStream *st;
3356     char *ipaddr;
3357     URLContext *h = NULL;
3358     uint8_t *dummy_buf;
3359     int max_packet_size;
3360
3361     /* now we can open the relevant output stream */
3362     ctx = avformat_alloc_context();
3363     if (!ctx)
3364         return -1;
3365     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3366
3367     st = av_mallocz(sizeof(AVStream));
3368     if (!st)
3369         goto fail;
3370     ctx->nb_streams = 1;
3371     ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3372     if (!ctx->streams)
3373       goto fail;
3374     ctx->streams[0] = st;
3375
3376     if (!c->stream->feed ||
3377         c->stream->feed == c->stream)
3378         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3379     else
3380         memcpy(st,
3381                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3382                sizeof(AVStream));
3383     st->priv_data = NULL;
3384
3385     /* build destination RTP address */
3386     ipaddr = inet_ntoa(dest_addr->sin_addr);
3387
3388     switch(c->rtp_protocol) {
3389     case RTSP_LOWER_TRANSPORT_UDP:
3390     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3391         /* RTP/UDP case */
3392
3393         /* XXX: also pass as parameter to function ? */
3394         if (c->stream->is_multicast) {
3395             int ttl;
3396             ttl = c->stream->multicast_ttl;
3397             if (!ttl)
3398                 ttl = 16;
3399             snprintf(ctx->filename, sizeof(ctx->filename),
3400                      "rtp://%s:%d?multicast=1&ttl=%d",
3401                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3402         } else {
3403             snprintf(ctx->filename, sizeof(ctx->filename),
3404                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3405         }
3406
3407         if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3408             goto fail;
3409         c->rtp_handles[stream_index] = h;
3410         max_packet_size = h->max_packet_size;
3411         break;
3412     case RTSP_LOWER_TRANSPORT_TCP:
3413         /* RTP/TCP case */
3414         c->rtsp_c = rtsp_c;
3415         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3416         break;
3417     default:
3418         goto fail;
3419     }
3420
3421     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3422              ipaddr, ntohs(dest_addr->sin_port),
3423              c->stream->filename, stream_index, c->protocol);
3424
3425     /* normally, no packets should be output here, but the packet size may be checked */
3426     if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3427         /* XXX: close stream */
3428         goto fail;
3429     }
3430     if (avformat_write_header(ctx, NULL) < 0) {
3431     fail:
3432         if (h)
3433             ffurl_close(h);
3434         av_free(ctx);
3435         return -1;
3436     }
3437     avio_close_dyn_buf(ctx->pb, &dummy_buf);
3438     av_free(dummy_buf);
3439
3440     c->rtp_ctx[stream_index] = ctx;
3441     return 0;
3442 }
3443
3444 /********************************************************************/
3445 /* avserver initialization */
3446
3447 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3448 {
3449     AVStream *fst;
3450
3451     fst = av_mallocz(sizeof(AVStream));
3452     if (!fst)
3453         return NULL;
3454     if (copy) {
3455         fst->codec = avcodec_alloc_context3(NULL);
3456         memcpy(fst->codec, codec, sizeof(AVCodecContext));
3457         if (codec->extradata_size) {
3458             fst->codec->extradata = av_malloc(codec->extradata_size);
3459             memcpy(fst->codec->extradata, codec->extradata,
3460                 codec->extradata_size);
3461         }
3462     } else {
3463         /* live streams must use the actual feed's codec since it may be
3464          * updated later to carry extradata needed by the streams.
3465          */
3466         fst->codec = codec;
3467     }
3468     fst->priv_data = av_mallocz(sizeof(FeedData));
3469     fst->index = stream->nb_streams;
3470     avpriv_set_pts_info(fst, 33, 1, 90000);
3471     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3472     stream->streams[stream->nb_streams++] = fst;
3473     return fst;
3474 }
3475
3476 /* return the stream number in the feed */
3477 static int add_av_stream(FFStream *feed, AVStream *st)
3478 {
3479     AVStream *fst;
3480     AVCodecContext *av, *av1;
3481     int i;
3482
3483     av = st->codec;
3484     for(i=0;i<feed->nb_streams;i++) {
3485         st = feed->streams[i];
3486         av1 = st->codec;
3487         if (av1->codec_id == av->codec_id &&
3488             av1->codec_type == av->codec_type &&
3489             av1->bit_rate == av->bit_rate) {
3490
3491             switch(av->codec_type) {
3492             case AVMEDIA_TYPE_AUDIO:
3493                 if (av1->channels == av->channels &&
3494                     av1->sample_rate == av->sample_rate)
3495                     return i;
3496                 break;
3497             case AVMEDIA_TYPE_VIDEO:
3498                 if (av1->width == av->width &&
3499                     av1->height == av->height &&
3500                     av1->time_base.den == av->time_base.den &&
3501                     av1->time_base.num == av->time_base.num &&
3502                     av1->gop_size == av->gop_size)
3503                     return i;
3504                 break;
3505             default:
3506                 abort();
3507             }
3508         }
3509     }
3510
3511     fst = add_av_stream1(feed, av, 0);
3512     if (!fst)
3513         return -1;
3514     return feed->nb_streams - 1;
3515 }
3516
3517 static void remove_stream(FFStream *stream)
3518 {
3519     FFStream **ps;
3520     ps = &first_stream;
3521     while (*ps != NULL) {
3522         if (*ps == stream)
3523             *ps = (*ps)->next;
3524         else
3525             ps = &(*ps)->next;
3526     }
3527 }
3528
3529 /* specific mpeg4 handling : we extract the raw parameters */
3530 static void extract_mpeg4_header(AVFormatContext *infile)
3531 {
3532     int mpeg4_count, i, size;
3533     AVPacket pkt;
3534     AVStream *st;
3535     const uint8_t *p;
3536
3537     mpeg4_count = 0;
3538     for(i=0;i<infile->nb_streams;i++) {
3539         st = infile->streams[i];
3540         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3541             st->codec->extradata_size == 0) {
3542             mpeg4_count++;
3543         }
3544     }
3545     if (!mpeg4_count)
3546         return;
3547
3548     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3549     while (mpeg4_count > 0) {
3550         if (av_read_packet(infile, &pkt) < 0)
3551             break;
3552         st = infile->streams[pkt.stream_index];
3553         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3554             st->codec->extradata_size == 0) {
3555             av_freep(&st->codec->extradata);
3556             /* fill extradata with the header */
3557             /* XXX: we make hard suppositions here ! */
3558             p = pkt.data;
3559             while (p < pkt.data + pkt.size - 4) {
3560                 /* stop when vop header is found */
3561                 if (p[0] == 0x00 && p[1] == 0x00 &&
3562                     p[2] == 0x01 && p[3] == 0xb6) {
3563                     size = p - pkt.data;
3564                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3565                     st->codec->extradata = av_malloc(size);
3566                     st->codec->extradata_size = size;
3567                     memcpy(st->codec->extradata, pkt.data, size);
3568                     break;
3569                 }
3570                 p++;
3571             }
3572             mpeg4_count--;
3573         }
3574         av_free_packet(&pkt);
3575     }
3576 }
3577
3578 /* compute the needed AVStream for each file */
3579 static void build_file_streams(void)
3580 {
3581     FFStream *stream, *stream_next;
3582     int i, ret;
3583
3584     /* gather all streams */
3585     for(stream = first_stream; stream != NULL; stream = stream_next) {
3586         AVFormatContext *infile = NULL;
3587         stream_next = stream->next;
3588         if (stream->stream_type == STREAM_TYPE_LIVE &&
3589             !stream->feed) {
3590             /* the stream comes from a file */
3591             /* try to open the file */
3592             /* open stream */
3593             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3594                 /* specific case : if transport stream output to RTP,
3595                    we use a raw transport stream reader */
3596                 av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3597             }
3598
3599             http_log("Opening file '%s'\n", stream->feed_filename);
3600             if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3601                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3602                 /* remove stream (no need to spend more time on it) */
3603             fail:
3604                 remove_stream(stream);
3605             } else {
3606                 /* find all the AVStreams inside and reference them in
3607                    'stream' */
3608                 if (avformat_find_stream_info(infile, NULL) < 0) {
3609                     http_log("Could not find codec parameters from '%s'\n",
3610                              stream->feed_filename);
3611                     avformat_close_input(&infile);
3612                     goto fail;
3613                 }
3614                 extract_mpeg4_header(infile);
3615
3616                 for(i=0;i<infile->nb_streams;i++)
3617                     add_av_stream1(stream, infile->streams[i]->codec, 1);
3618
3619                 avformat_close_input(&infile);
3620             }
3621         }
3622     }
3623 }
3624
3625 /* compute the needed AVStream for each feed */
3626 static void build_feed_streams(void)
3627 {
3628     FFStream *stream, *feed;
3629     int i;
3630
3631     /* gather all streams */
3632     for(stream = first_stream; stream != NULL; stream = stream->next) {
3633         feed = stream->feed;
3634         if (feed) {
3635             if (stream->is_feed) {
3636                 for(i=0;i<stream->nb_streams;i++)
3637                     stream->feed_streams[i] = i;
3638             } else {
3639                 /* we handle a stream coming from a feed */
3640                 for(i=0;i<stream->nb_streams;i++)
3641                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3642             }
3643         }
3644     }
3645
3646     /* create feed files if needed */
3647     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3648         int fd;
3649
3650         if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3651             /* See if it matches */
3652             AVFormatContext *s = NULL;
3653             int matches = 0;
3654
3655             if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3656                 /* Now see if it matches */
3657                 if (s->nb_streams == feed->nb_streams) {
3658                     matches = 1;
3659                     for(i=0;i<s->nb_streams;i++) {
3660                         AVStream *sf, *ss;
3661                         sf = feed->streams[i];
3662                         ss = s->streams[i];
3663
3664                         if (sf->index != ss->index ||
3665                             sf->id != ss->id) {
3666                             http_log("Index & Id do not match for stream %d (%s)\n",
3667                                    i, feed->feed_filename);
3668                             matches = 0;
3669                         } else {
3670                             AVCodecContext *ccf, *ccs;
3671
3672                             ccf = sf->codec;
3673                             ccs = ss->codec;
3674 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3675
3676                             if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3677                                 http_log("Codecs do not match for stream %d\n", i);
3678                                 matches = 0;
3679                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3680                                 http_log("Codec bitrates do not match for stream %d\n", i);
3681                                 matches = 0;
3682                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3683                                 if (CHECK_CODEC(time_base.den) ||
3684                                     CHECK_CODEC(time_base.num) ||
3685                                     CHECK_CODEC(width) ||
3686                                     CHECK_CODEC(height)) {
3687                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3688                                     matches = 0;
3689                                 }
3690                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3691                                 if (CHECK_CODEC(sample_rate) ||
3692                                     CHECK_CODEC(channels) ||
3693                                     CHECK_CODEC(frame_size)) {
3694                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3695                                     matches = 0;
3696                                 }
3697                             } else {
3698                                 http_log("Unknown codec type\n");
3699                                 matches = 0;
3700                             }
3701                         }
3702                         if (!matches)
3703                             break;
3704                     }
3705                 } else
3706                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3707                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3708
3709                 avformat_close_input(&s);
3710             } else
3711                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3712                         feed->feed_filename);
3713
3714             if (!matches) {
3715                 if (feed->readonly) {
3716                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3717                         feed->feed_filename);
3718                     exit(1);
3719                 }
3720                 unlink(feed->feed_filename);
3721             }
3722         }
3723         if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3724             AVFormatContext s1 = {0}, *s = &s1;
3725
3726             if (feed->readonly) {
3727                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3728                     feed->feed_filename);
3729                 exit(1);
3730             }
3731
3732             /* only write the header of the ffm file */
3733             if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3734                 http_log("Could not open output feed file '%s'\n",
3735                          feed->feed_filename);
3736                 exit(1);
3737             }
3738             s->oformat = feed->fmt;
3739             s->nb_streams = feed->nb_streams;
3740             s->streams = feed->streams;
3741             if (avformat_write_header(s, NULL) < 0) {
3742                 http_log("Container doesn't supports the required parameters\n");
3743                 exit(1);
3744             }
3745             /* XXX: need better api */
3746             av_freep(&s->priv_data);
3747             avio_close(s->pb);
3748         }
3749         /* get feed size and write index */
3750         fd = open(feed->feed_filename, O_RDONLY);
3751         if (fd < 0) {
3752             http_log("Could not open output feed file '%s'\n",
3753                     feed->feed_filename);
3754             exit(1);
3755         }
3756
3757         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3758         feed->feed_size = lseek(fd, 0, SEEK_END);
3759         /* ensure that we do not wrap before the end of file */
3760         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3761             feed->feed_max_size = feed->feed_size;
3762
3763         close(fd);
3764     }
3765 }
3766
3767 /* compute the bandwidth used by each stream */
3768 static void compute_bandwidth(void)
3769 {
3770     unsigned bandwidth;
3771     int i;
3772     FFStream *stream;
3773
3774     for(stream = first_stream; stream != NULL; stream = stream->next) {
3775         bandwidth = 0;
3776         for(i=0;i<stream->nb_streams;i++) {
3777             AVStream *st = stream->streams[i];
3778             switch(st->codec->codec_type) {
3779             case AVMEDIA_TYPE_AUDIO:
3780             case AVMEDIA_TYPE_VIDEO:
3781                 bandwidth += st->codec->bit_rate;
3782                 break;
3783             default:
3784                 break;
3785             }
3786         }
3787         stream->bandwidth = (bandwidth + 999) / 1000;
3788     }
3789 }
3790
3791 /* add a codec and set the default parameters */
3792 static void add_codec(FFStream *stream, AVCodecContext *av)
3793 {
3794     AVStream *st;
3795
3796     /* compute default parameters */
3797     switch(av->codec_type) {
3798     case AVMEDIA_TYPE_AUDIO:
3799         if (av->bit_rate == 0)
3800             av->bit_rate = 64000;
3801         if (av->sample_rate == 0)
3802             av->sample_rate = 22050;
3803         if (av->channels == 0)
3804             av->channels = 1;
3805         break;
3806     case AVMEDIA_TYPE_VIDEO:
3807         if (av->bit_rate == 0)
3808             av->bit_rate = 64000;
3809         if (av->time_base.num == 0){
3810             av->time_base.den = 5;
3811             av->time_base.num = 1;
3812         }
3813         if (av->width == 0 || av->height == 0) {
3814             av->width = 160;
3815             av->height = 128;
3816         }
3817         /* Bitrate tolerance is less for streaming */
3818         if (av->bit_rate_tolerance == 0)
3819             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3820                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3821         if (av->qmin == 0)
3822             av->qmin = 3;
3823         if (av->qmax == 0)
3824             av->qmax = 31;
3825         if (av->max_qdiff == 0)
3826             av->max_qdiff = 3;
3827         av->qcompress = 0.5;
3828         av->qblur = 0.5;
3829
3830         if (!av->nsse_weight)
3831             av->nsse_weight = 8;
3832
3833         av->frame_skip_cmp = FF_CMP_DCTMAX;
3834         if (!av->me_method)
3835             av->me_method = ME_EPZS;
3836         av->rc_buffer_aggressivity = 1.0;
3837
3838         if (!av->rc_eq)
3839             av->rc_eq = "tex^qComp";
3840         if (!av->i_quant_factor)
3841             av->i_quant_factor = -0.8;
3842         if (!av->b_quant_factor)
3843             av->b_quant_factor = 1.25;
3844         if (!av->b_quant_offset)
3845             av->b_quant_offset = 1.25;
3846         if (!av->rc_max_rate)
3847             av->rc_max_rate = av->bit_rate * 2;
3848
3849         if (av->rc_max_rate && !av->rc_buffer_size) {
3850             av->rc_buffer_size = av->rc_max_rate;
3851         }
3852
3853
3854         break;
3855     default:
3856         abort();
3857     }
3858
3859     st = av_mallocz(sizeof(AVStream));
3860     if (!st)
3861         return;
3862     st->codec = avcodec_alloc_context3(NULL);
3863     stream->streams[stream->nb_streams++] = st;
3864     memcpy(st->codec, av, sizeof(AVCodecContext));
3865 }
3866
3867 static enum CodecID opt_audio_codec(const char *arg)
3868 {
3869     AVCodec *p= avcodec_find_encoder_by_name(arg);
3870
3871     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3872         return CODEC_ID_NONE;
3873
3874     return p->id;
3875 }
3876
3877 static enum CodecID opt_video_codec(const char *arg)
3878 {
3879     AVCodec *p= avcodec_find_encoder_by_name(arg);
3880
3881     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3882         return CODEC_ID_NONE;
3883
3884     return p->id;
3885 }
3886
3887 /* simplistic plugin support */
3888
3889 #if HAVE_DLOPEN
3890 static void load_module(const char *filename)
3891 {
3892     void *dll;
3893     void (*init_func)(void);
3894     dll = dlopen(filename, RTLD_NOW);
3895     if (!dll) {
3896         fprintf(stderr, "Could not load module '%s' - %s\n",
3897                 filename, dlerror());
3898         return;
3899     }
3900
3901     init_func = dlsym(dll, "avserver_module_init");
3902     if (!init_func) {
3903         fprintf(stderr,
3904                 "%s: init function 'avserver_module_init()' not found\n",
3905                 filename);
3906         dlclose(dll);
3907     }
3908
3909     init_func();
3910 }
3911 #endif
3912
3913 static int avserver_opt_default(const char *opt, const char *arg,
3914                        AVCodecContext *avctx, int type)
3915 {
3916     int ret = 0;
3917     const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3918     if(o)
3919         ret = av_opt_set(avctx, opt, arg, 0);
3920     return ret;
3921 }
3922
3923 static int avserver_opt_preset(const char *arg,
3924                        AVCodecContext *avctx, int type,
3925                        enum CodecID *audio_id, enum CodecID *video_id)
3926 {
3927     FILE *f=NULL;
3928     char filename[1000], tmp[1000], tmp2[1000], line[1000];
3929     int ret = 0;
3930     AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3931
3932     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3933                               codec ? codec->name : NULL))) {
3934         fprintf(stderr, "File for preset '%s' not found\n", arg);
3935         return 1;
3936     }
3937
3938     while(!feof(f)){
3939         int e= fscanf(f, "%999[^\n]\n", line) - 1;
3940         if(line[0] == '#' && !e)
3941             continue;
3942         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3943         if(e){
3944             fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3945             ret = 1;
3946             break;
3947         }
3948         if(!strcmp(tmp, "acodec")){
3949             *audio_id = opt_audio_codec(tmp2);
3950         }else if(!strcmp(tmp, "vcodec")){
3951             *video_id = opt_video_codec(tmp2);
3952         }else if(!strcmp(tmp, "scodec")){
3953             /* opt_subtitle_codec(tmp2); */
3954         }else if(avserver_opt_default(tmp, tmp2, avctx, type) < 0){
3955             fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3956             ret = 1;
3957             break;
3958         }
3959     }
3960
3961     fclose(f);
3962
3963     return ret;
3964 }
3965
3966 static AVOutputFormat *avserver_guess_format(const char *short_name, const char *filename,
3967                                              const char *mime_type)
3968 {
3969     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3970
3971     if (fmt) {
3972         AVOutputFormat *stream_fmt;
3973         char stream_format_name[64];
3974
3975         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3976         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3977
3978         if (stream_fmt)
3979             fmt = stream_fmt;
3980     }
3981
3982     return fmt;
3983 }
3984
3985 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
3986 {
3987     va_list vl;
3988     va_start(vl, fmt);
3989     fprintf(stderr, "%s:%d: ", filename, line_num);
3990     vfprintf(stderr, fmt, vl);
3991     va_end(vl);
3992
3993     (*errors)++;
3994 }
3995
3996 static int parse_ffconfig(const char *filename)
3997 {
3998     FILE *f;
3999     char line[1024];
4000     char cmd[64];
4001     char arg[1024];
4002     const char *p;
4003     int val, errors, line_num;
4004     FFStream **last_stream, *stream, *redirect;
4005     FFStream **last_feed, *feed, *s;
4006     AVCodecContext audio_enc, video_enc;
4007     enum CodecID audio_id, video_id;
4008
4009     f = fopen(filename, "r");
4010     if (!f) {
4011         perror(filename);
4012         return -1;
4013     }
4014
4015     errors = 0;
4016     line_num = 0;
4017     first_stream = NULL;
4018     last_stream = &first_stream;
4019     first_feed = NULL;
4020     last_feed = &first_feed;
4021     stream = NULL;
4022     feed = NULL;
4023     redirect = NULL;
4024     audio_id = CODEC_ID_NONE;
4025     video_id = CODEC_ID_NONE;
4026
4027 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4028     for(;;) {
4029         if (fgets(line, sizeof(line), f) == NULL)
4030             break;
4031         line_num++;
4032         p = line;
4033         while (isspace(*p))
4034             p++;
4035         if (*p == '\0' || *p == '#')
4036             continue;
4037
4038         get_arg(cmd, sizeof(cmd), &p);
4039
4040         if (!av_strcasecmp(cmd, "Port")) {
4041             get_arg(arg, sizeof(arg), &p);
4042             val = atoi(arg);
4043             if (val < 1 || val > 65536) {
4044                 ERROR("Invalid_port: %s\n", arg);
4045             }
4046             my_http_addr.sin_port = htons(val);
4047         } else if (!av_strcasecmp(cmd, "BindAddress")) {
4048             get_arg(arg, sizeof(arg), &p);
4049             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4050                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4051             }
4052         } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4053             avserver_daemon = 0;
4054         } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4055             get_arg(arg, sizeof(arg), &p);
4056             val = atoi(arg);
4057             if (val < 1 || val > 65536) {
4058                 ERROR("%s:%d: Invalid port: %s\n", arg);
4059             }
4060             my_rtsp_addr.sin_port = htons(atoi(arg));
4061         } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4062             get_arg(arg, sizeof(arg), &p);
4063             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4064                 ERROR("Invalid host/IP address: %s\n", arg);
4065             }
4066         } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4067             get_arg(arg, sizeof(arg), &p);
4068             val = atoi(arg);
4069             if (val < 1 || val > 65536) {
4070                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4071             }
4072             nb_max_http_connections = val;
4073         } else if (!av_strcasecmp(cmd, "MaxClients")) {
4074             get_arg(arg, sizeof(arg), &p);
4075             val = atoi(arg);
4076             if (val < 1 || val > nb_max_http_connections) {
4077                 ERROR("Invalid MaxClients: %s\n", arg);
4078             } else {
4079                 nb_max_connections = val;
4080             }
4081         } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4082             int64_t llval;
4083             get_arg(arg, sizeof(arg), &p);
4084             llval = atoll(arg);
4085             if (llval < 10 || llval > 10000000) {
4086                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4087             } else
4088                 max_bandwidth = llval;
4089         } else if (!av_strcasecmp(cmd, "CustomLog")) {
4090             if (!avserver_debug)
4091                 get_arg(logfilename, sizeof(logfilename), &p);
4092         } else if (!av_strcasecmp(cmd, "<Feed")) {
4093             /*********************************************/
4094             /* Feed related options */
4095             char *q;
4096             if (stream || feed) {
4097                 ERROR("Already in a tag\n");
4098             } else {
4099                 feed = av_mallocz(sizeof(FFStream));
4100                 get_arg(feed->filename, sizeof(feed->filename), &p);
4101                 q = strrchr(feed->filename, '>');
4102                 if (*q)
4103                     *q = '\0';
4104
4105                 for (s = first_feed; s; s = s->next) {
4106                     if (!strcmp(feed->filename, s->filename)) {
4107                         ERROR("Feed '%s' already registered\n", s->filename);
4108                     }
4109                 }
4110
4111                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4112                 /* defaut feed file */
4113                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4114                          "/tmp/%s.ffm", feed->filename);
4115                 feed->feed_max_size = 5 * 1024 * 1024;
4116                 feed->is_feed = 1;
4117                 feed->feed = feed; /* self feeding :-) */
4118
4119                 /* add in stream list */
4120                 *last_stream = feed;
4121                 last_stream = &feed->next;
4122                 /* add in feed list */
4123                 *last_feed = feed;
4124                 last_feed = &feed->next_feed;
4125             }
4126         } else if (!av_strcasecmp(cmd, "Launch")) {
4127             if (feed) {
4128                 int i;
4129
4130                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4131
4132                 for (i = 0; i < 62; i++) {
4133                     get_arg(arg, sizeof(arg), &p);
4134                     if (!arg[0])
4135                         break;
4136
4137                     feed->child_argv[i] = av_strdup(arg);
4138                 }
4139
4140                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4141
4142                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4143                     "http://%s:%d/%s",
4144                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4145                     inet_ntoa(my_http_addr.sin_addr),
4146                     ntohs(my_http_addr.sin_port), feed->filename);
4147             }
4148         } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4149             if (feed) {
4150                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4151                 feed->readonly = 1;
4152             } else if (stream) {
4153                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4154             }
4155         } else if (!av_strcasecmp(cmd, "File")) {
4156             if (feed) {
4157                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4158             } else if (stream)
4159                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4160         } else if (!av_strcasecmp(cmd, "Truncate")) {
4161             if (feed) {
4162                 get_arg(arg, sizeof(arg), &p);
4163                 feed->truncate = strtod(arg, NULL);
4164             }
4165         } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4166             if (feed) {
4167                 char *p1;
4168                 double fsize;
4169
4170                 get_arg(arg, sizeof(arg), &p);
4171                 p1 = arg;
4172                 fsize = strtod(p1, &p1);
4173                 switch(toupper(*p1)) {
4174                 case 'K':
4175                     fsize *= 1024;
4176                     break;
4177                 case 'M':
4178                     fsize *= 1024 * 1024;
4179                     break;
4180                 case 'G':
4181                     fsize *= 1024 * 1024 * 1024;
4182                     break;
4183                 }
4184                 feed->feed_max_size = (int64_t)fsize;
4185                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4186                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4187                 }
4188             }
4189         } else if (!av_strcasecmp(cmd, "</Feed>")) {
4190             if (!feed) {
4191                 ERROR("No corresponding <Feed> for </Feed>\n");
4192             }
4193             feed = NULL;
4194         } else if (!av_strcasecmp(cmd, "<Stream")) {
4195             /*********************************************/
4196             /* Stream related options */
4197             char *q;
4198             if (stream || feed) {
4199                 ERROR("Already in a tag\n");
4200             } else {
4201                 FFStream *s;
4202                 stream = av_mallocz(sizeof(FFStream));
4203                 get_arg(stream->filename, sizeof(stream->filename), &p);
4204                 q = strrchr(stream->filename, '>');
4205                 if (*q)
4206                     *q = '\0';
4207
4208                 for (s = first_stream; s; s = s->next) {
4209                     if (!strcmp(stream->filename, s->filename)) {
4210                         ERROR("Stream '%s' already registered\n", s->filename);
4211                     }
4212                 }
4213
4214                 stream->fmt = avserver_guess_format(NULL, stream->filename, NULL);
4215                 avcodec_get_context_defaults3(&video_enc, NULL);
4216                 avcodec_get_context_defaults3(&audio_enc, NULL);
4217                 audio_id = CODEC_ID_NONE;
4218                 video_id = CODEC_ID_NONE;
4219                 if (stream->fmt) {
4220                     audio_id = stream->fmt->audio_codec;
4221                     video_id = stream->fmt->video_codec;
4222                 }
4223
4224                 *last_stream = stream;
4225                 last_stream = &stream->next;
4226             }
4227         } else if (!av_strcasecmp(cmd, "Feed")) {
4228             get_arg(arg, sizeof(arg), &p);
4229             if (stream) {
4230                 FFStream *sfeed;
4231
4232                 sfeed = first_feed;
4233                 while (sfeed != NULL) {
4234                     if (!strcmp(sfeed->filename, arg))
4235                         break;
4236                     sfeed = sfeed->next_feed;
4237                 }
4238                 if (!sfeed)
4239                     ERROR("feed '%s' not defined\n", arg);
4240                 else
4241                     stream->feed = sfeed;
4242             }
4243         } else if (!av_strcasecmp(cmd, "Format")) {
4244             get_arg(arg, sizeof(arg), &p);
4245             if (stream) {
4246                 if (!strcmp(arg, "status")) {
4247                     stream->stream_type = STREAM_TYPE_STATUS;
4248                     stream->fmt = NULL;
4249                 } else {
4250                     stream->stream_type = STREAM_TYPE_LIVE;
4251                     /* jpeg cannot be used here, so use single frame jpeg */
4252                     if (!strcmp(arg, "jpeg"))
4253                         strcpy(arg, "mjpeg");
4254                     stream->fmt = avserver_guess_format(arg, NULL, NULL);
4255                     if (!stream->fmt) {
4256                         ERROR("Unknown Format: %s\n", arg);
4257                     }
4258                 }
4259                 if (stream->fmt) {
4260                     audio_id = stream->fmt->audio_codec;
4261                     video_id = stream->fmt->video_codec;
4262                 }
4263             }
4264         } else if (!av_strcasecmp(cmd, "InputFormat")) {
4265             get_arg(arg, sizeof(arg), &p);
4266             if (stream) {
4267                 stream->ifmt = av_find_input_format(arg);
4268                 if (!stream->ifmt) {
4269                     ERROR("Unknown input format: %s\n", arg);
4270                 }
4271             }
4272         } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4273             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4274                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4275             } else {
4276                 ERROR("FaviconURL only permitted for status streams\n");
4277             }
4278         } else if (!av_strcasecmp(cmd, "Author")) {
4279             if (stream)
4280                 get_arg(stream->author, sizeof(stream->author), &p);
4281         } else if (!av_strcasecmp(cmd, "Comment")) {
4282             if (stream)
4283                 get_arg(stream->comment, sizeof(stream->comment), &p);
4284         } else if (!av_strcasecmp(cmd, "Copyright")) {
4285             if (stream)
4286                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4287         } else if (!av_strcasecmp(cmd, "Title")) {
4288             if (stream)
4289                 get_arg(stream->title, sizeof(stream->title), &p);
4290         } else if (!av_strcasecmp(cmd, "Preroll")) {
4291             get_arg(arg, sizeof(arg), &p);
4292             if (stream)
4293                 stream->prebuffer = atof(arg) * 1000;
4294         } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4295             if (stream)
4296                 stream->send_on_key = 1;
4297         } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4298             get_arg(arg, sizeof(arg), &p);
4299             audio_id = opt_audio_codec(arg);
4300             if (audio_id == CODEC_ID_NONE) {
4301                 ERROR("Unknown AudioCodec: %s\n", arg);
4302             }
4303         } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4304             get_arg(arg, sizeof(arg), &p);
4305             video_id = opt_video_codec(arg);
4306             if (video_id == CODEC_ID_NONE) {
4307                 ERROR("Unknown VideoCodec: %s\n", arg);
4308             }
4309         } else if (!av_strcasecmp(cmd, "MaxTime")) {
4310             get_arg(arg, sizeof(arg), &p);
4311             if (stream)
4312                 stream->max_time = atof(arg) * 1000;
4313         } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4314             get_arg(arg, sizeof(arg), &p);
4315             if (stream)
4316                 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4317         } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4318             get_arg(arg, sizeof(arg), &p);
4319             if (stream)
4320                 audio_enc.channels = atoi(arg);
4321         } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4322             get_arg(arg, sizeof(arg), &p);
4323             if (stream)
4324                 audio_enc.sample_rate = atoi(arg);
4325         } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4326             get_arg(arg, sizeof(arg), &p);
4327             if (stream) {
4328 //                audio_enc.quality = atof(arg) * 1000;
4329             }
4330         } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4331             if (stream) {
4332                 int minrate, maxrate;
4333
4334                 get_arg(arg, sizeof(arg), &p);
4335
4336                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4337                     video_enc.rc_min_rate = minrate * 1000;
4338                     video_enc.rc_max_rate = maxrate * 1000;
4339                 } else {
4340                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4341                 }
4342             }
4343         } else if (!av_strcasecmp(cmd, "Debug")) {
4344             if (stream) {
4345                 get_arg(arg, sizeof(arg), &p);
4346                 video_enc.debug = strtol(arg,0,0);
4347             }
4348         } else if (!av_strcasecmp(cmd, "Strict")) {
4349             if (stream) {
4350                 get_arg(arg, sizeof(arg), &p);
4351                 video_enc.strict_std_compliance = atoi(arg);
4352             }
4353         } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4354             if (stream) {
4355                 get_arg(arg, sizeof(arg), &p);
4356                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4357             }
4358         } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4359             if (stream) {
4360                 get_arg(arg, sizeof(arg), &p);
4361                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4362             }
4363         } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4364             get_arg(arg, sizeof(arg), &p);
4365             if (stream) {
4366                 video_enc.bit_rate = atoi(arg) * 1000;
4367             }
4368         } else if (!av_strcasecmp(cmd, "VideoSize")) {
4369             get_arg(arg, sizeof(arg), &p);
4370             if (stream) {
4371                 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4372                 if ((video_enc.width % 16) != 0 ||
4373                     (video_enc.height % 16) != 0) {
4374                     ERROR("Image size must be a multiple of 16\n");
4375                 }
4376             }
4377         } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4378             get_arg(arg, sizeof(arg), &p);
4379             if (stream) {
4380                 AVRational frame_rate;
4381                 if (av_parse_video_rate(&frame_rate, arg) < 0) {
4382                     ERROR("Incorrect frame rate: %s\n", arg);
4383                 } else {
4384                     video_enc.time_base.num = frame_rate.den;
4385                     video_enc.time_base.den = frame_rate.num;
4386                 }
4387             }
4388         } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4389             get_arg(arg, sizeof(arg), &p);
4390             if (stream)
4391                 video_enc.gop_size = atoi(arg);
4392         } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4393             if (stream)
4394                 video_enc.gop_size = 1;
4395         } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4396             if (stream)
4397                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4398         } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4399             if (stream) {
4400                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4401                 video_enc.flags |= CODEC_FLAG_4MV;
4402             }
4403         } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4404                    !av_strcasecmp(cmd, "AVOptionAudio")) {
4405             char arg2[1024];
4406             AVCodecContext *avctx;
4407             int type;
4408             get_arg(arg, sizeof(arg), &p);
4409             get_arg(arg2, sizeof(arg2), &p);
4410             if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4411                 avctx = &video_enc;
4412                 type = AV_OPT_FLAG_VIDEO_PARAM;
4413             } else {
4414                 avctx = &audio_enc;
4415                 type = AV_OPT_FLAG_AUDIO_PARAM;
4416             }
4417             if (avserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4418                 ERROR("AVOption error: %s %s\n", arg, arg2);
4419             }
4420         } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4421                    !av_strcasecmp(cmd, "AVPresetAudio")) {
4422             AVCodecContext *avctx;
4423             int type;
4424             get_arg(arg, sizeof(arg), &p);
4425             if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4426                 avctx = &video_enc;
4427                 video_enc.codec_id = video_id;
4428                 type = AV_OPT_FLAG_VIDEO_PARAM;
4429             } else {
4430                 avctx = &audio_enc;
4431                 audio_enc.codec_id = audio_id;
4432                 type = AV_OPT_FLAG_AUDIO_PARAM;
4433             }
4434             if (avserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4435                 ERROR("AVPreset error: %s\n", arg);
4436             }
4437         } else if (!av_strcasecmp(cmd, "VideoTag")) {
4438             get_arg(arg, sizeof(arg), &p);
4439             if ((strlen(arg) == 4) && stream)
4440                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4441         } else if (!av_strcasecmp(cmd, "BitExact")) {
4442             if (stream)
4443                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4444         } else if (!av_strcasecmp(cmd, "DctFastint")) {
4445             if (stream)
4446                 video_enc.dct_algo  = FF_DCT_FASTINT;
4447         } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4448             if (stream)
4449                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4450         } else if (!av_strcasecmp(cmd, "Qscale")) {
4451             get_arg(arg, sizeof(arg), &p);
4452             if (stream) {
4453                 video_enc.flags |= CODEC_FLAG_QSCALE;
4454                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4455             }
4456         } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4457             get_arg(arg, sizeof(arg), &p);
4458             if (stream) {
4459                 video_enc.max_qdiff = atoi(arg);
4460                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4461                     ERROR("VideoQDiff out of range\n");
4462                 }
4463             }
4464         } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4465             get_arg(arg, sizeof(arg), &p);
4466             if (stream) {
4467                 video_enc.qmax = atoi(arg);
4468                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4469                     ERROR("VideoQMax out of range\n");
4470                 }
4471             }
4472         } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4473             get_arg(arg, sizeof(arg), &p);
4474             if (stream) {
4475                 video_enc.qmin = atoi(arg);
4476                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4477                     ERROR("VideoQMin out of range\n");
4478                 }
4479             }
4480         } else if (!av_strcasecmp(cmd, "LumaElim")) {
4481             get_arg(arg, sizeof(arg), &p);
4482             if (stream)
4483                 video_enc.luma_elim_threshold = atoi(arg);
4484         } else if (!av_strcasecmp(cmd, "ChromaElim")) {
4485             get_arg(arg, sizeof(arg), &p);
4486             if (stream)
4487                 video_enc.chroma_elim_threshold = atoi(arg);
4488         } else if (!av_strcasecmp(cmd, "LumiMask")) {
4489             get_arg(arg, sizeof(arg), &p);
4490             if (stream)
4491                 video_enc.lumi_masking = atof(arg);
4492         } else if (!av_strcasecmp(cmd, "DarkMask")) {
4493             get_arg(arg, sizeof(arg), &p);
4494             if (stream)
4495                 video_enc.dark_masking = atof(arg);
4496         } else if (!av_strcasecmp(cmd, "NoVideo")) {
4497             video_id = CODEC_ID_NONE;
4498         } else if (!av_strcasecmp(cmd, "NoAudio")) {
4499             audio_id = CODEC_ID_NONE;
4500         } else if (!av_strcasecmp(cmd, "ACL")) {
4501             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4502         } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4503             if (stream) {
4504                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4505             }
4506         } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4507             get_arg(arg, sizeof(arg), &p);
4508             if (stream) {
4509                 av_freep(&stream->rtsp_option);
4510                 stream->rtsp_option = av_strdup(arg);
4511             }
4512         } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4513             get_arg(arg, sizeof(arg), &p);
4514             if (stream) {
4515                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4516                     ERROR("Invalid host/IP address: %s\n", arg);
4517                 }
4518                 stream->is_multicast = 1;
4519                 stream->loop = 1; /* default is looping */
4520             }
4521         } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4522             get_arg(arg, sizeof(arg), &p);
4523             if (stream)
4524                 stream->multicast_port = atoi(arg);
4525         } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4526             get_arg(arg, sizeof(arg), &p);
4527             if (stream)
4528                 stream->multicast_ttl = atoi(arg);
4529         } else if (!av_strcasecmp(cmd, "NoLoop")) {
4530             if (stream)
4531                 stream->loop = 0;
4532         } else if (!av_strcasecmp(cmd, "</Stream>")) {
4533             if (!stream) {
4534                 ERROR("No corresponding <Stream> for </Stream>\n");
4535             } else {
4536                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4537                     if (audio_id != CODEC_ID_NONE) {
4538                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4539                         audio_enc.codec_id = audio_id;
4540                         add_codec(stream, &audio_enc);
4541                     }
4542                     if (video_id != CODEC_ID_NONE) {
4543                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4544                         video_enc.codec_id = video_id;
4545                         add_codec(stream, &video_enc);
4546                     }
4547                 }
4548                 stream = NULL;
4549             }
4550         } else if (!av_strcasecmp(cmd, "<Redirect")) {
4551             /*********************************************/
4552             char *q;
4553             if (stream || feed || redirect) {
4554                 ERROR("Already in a tag\n");
4555             } else {
4556                 redirect = av_mallocz(sizeof(FFStream));
4557                 *last_stream = redirect;
4558                 last_stream = &redirect->next;
4559
4560                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4561                 q = strrchr(redirect->filename, '>');
4562                 if (*q)
4563                     *q = '\0';
4564                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4565             }
4566         } else if (!av_strcasecmp(cmd, "URL")) {
4567             if (redirect)
4568                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4569         } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4570             if (!redirect) {
4571                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4572             } else {
4573                 if (!redirect->feed_filename[0]) {
4574                     ERROR("No URL found for <Redirect>\n");
4575                 }
4576                 redirect = NULL;
4577             }
4578         } else if (!av_strcasecmp(cmd, "LoadModule")) {
4579             get_arg(arg, sizeof(arg), &p);
4580 #if HAVE_DLOPEN
4581             load_module(arg);
4582 #else
4583             ERROR("Module support not compiled into this version: '%s'\n", arg);
4584 #endif
4585         } else {
4586             ERROR("Incorrect keyword: '%s'\n", cmd);
4587         }
4588     }
4589 #undef ERROR
4590
4591     fclose(f);
4592     if (errors)
4593         return -1;
4594     else
4595         return 0;
4596 }
4597
4598 static void handle_child_exit(int sig)
4599 {
4600     pid_t pid;
4601     int status;
4602
4603     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4604         FFStream *feed;
4605
4606         for (feed = first_feed; feed; feed = feed->next) {
4607             if (feed->pid == pid) {
4608                 int uptime = time(0) - feed->pid_start;
4609
4610                 feed->pid = 0;
4611                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4612
4613                 if (uptime < 30)
4614                     /* Turn off any more restarts */
4615                     feed->child_argv = 0;
4616             }
4617         }
4618     }
4619
4620     need_to_start_children = 1;
4621 }
4622
4623 static void opt_debug(void)
4624 {
4625     avserver_debug = 1;
4626     avserver_daemon = 0;
4627     logfilename[0] = '-';
4628 }
4629
4630 static void show_help(void)
4631 {
4632     printf("usage: avserver [options]\n"
4633            "Hyper fast multi format Audio/Video streaming server\n");
4634     printf("\n");
4635     show_help_options(options, "Main options:\n", 0, 0);
4636 }
4637
4638 static const OptionDef options[] = {
4639 #include "cmdutils_common_opts.h"
4640     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4641     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4642     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/avserver.conf", "configfile" },
4643     { NULL },
4644 };
4645
4646 int main(int argc, char **argv)
4647 {
4648     struct sigaction sigact = { { 0 } };
4649
4650     parse_loglevel(argc, argv, options);
4651     av_register_all();
4652     avformat_network_init();
4653
4654     show_banner();
4655
4656     my_program_name = argv[0];
4657     my_program_dir = getcwd(0, 0);
4658     avserver_daemon = 1;
4659
4660     parse_options(NULL, argc, argv, options, NULL);
4661
4662     unsetenv("http_proxy");             /* Kill the http_proxy */
4663
4664     av_lfg_init(&random_state, av_get_random_seed());
4665
4666     sigact.sa_handler = handle_child_exit;
4667     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4668     sigaction(SIGCHLD, &sigact, 0);
4669
4670     if (parse_ffconfig(config_filename) < 0) {
4671         fprintf(stderr, "Incorrect config file - exiting.\n");
4672         exit(1);
4673     }
4674
4675     /* open log file if needed */
4676     if (logfilename[0] != '\0') {
4677         if (!strcmp(logfilename, "-"))
4678             logfile = stdout;
4679         else
4680             logfile = fopen(logfilename, "a");
4681         av_log_set_callback(http_av_log);
4682     }
4683
4684     build_file_streams();
4685
4686     build_feed_streams();
4687
4688     compute_bandwidth();
4689
4690     /* put the process in background and detach it from its TTY */
4691     if (avserver_daemon) {
4692         int pid;
4693
4694         pid = fork();
4695         if (pid < 0) {
4696             perror("fork");
4697             exit(1);
4698         } else if (pid > 0) {
4699             /* parent : exit */
4700             exit(0);
4701         } else {
4702             /* child */
4703             setsid();
4704             close(0);
4705             open("/dev/null", O_RDWR);
4706             if (strcmp(logfilename, "-") != 0) {
4707                 close(1);
4708                 dup(0);
4709             }
4710             close(2);
4711             dup(0);
4712         }
4713     }
4714
4715     /* signal init */
4716     signal(SIGPIPE, SIG_IGN);
4717
4718     if (avserver_daemon)
4719         chdir("/");
4720
4721     if (http_server() < 0) {
4722         http_log("Could not start server\n");
4723         exit(1);
4724     }
4725
4726     return 0;
4727 }