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