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