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