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