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