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