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