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