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