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