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