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