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