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