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